Introduction

In this post, I’ll walk you through how I built a serverless application that automatically checks for match schedules and sends email notifications using AWS services. This project leverages AWS Lambda, Amazon SNS, and Amazon EventBridge, demonstrating a practical use case of event-driven architecture in the cloud.

Why I did this?

Checking match schedules manually can be tedious, and missing a match can be frustrating. What if we could automate this process so that users receive timely notifications about upcoming matches?

Solution Overview

To solve this, I created an AWS-based system that:

  1. Fetches match schedules using a Lambda function.
  2. Triggers email notifications via Amazon SNS.
  3. Uses EventBridge as a scheduler to run the Lambda function at set intervals.

Implementation Steps

1. Setting Up the SNS Topic

  • Created an SNS topic in the AWS console.

Image description

Image description

  • Added an email subscription to receive notifications.

Image description

  • Confirmed the subscription via email.

Image description

Image description

I also created IAM roles and policies so that our SNS topic can communicate with our lambda function

Image description

Image description

2. Writing the Lambda Function

  • I Used Python to fetch match schedules from an API.
  • Processed the data and sent a message to SNS.
  • Deployed the function to AWS Lambda.

Sample Lambda Code (Python):

import os
import json
import urllib.request
import boto3
from datetime import datetime, timezone

def fetch_football_data(api_url, headers):
    request = urllib.request.Request(api_url, headers=headers)
    try:
        with urllib.request.urlopen(request) as response:
            return json.loads(response.read().decode())
    except Exception as e:
        print(f"Error fetching data from API: {e}")
        return None

def format_match_data(match):
    status = match.get("status", "Unknown")
    home_team = match.get("homeTeam", {}).get("name", "Unknown")
    away_team = match.get("awayTeam", {}).get("name", "Unknown")
    home_score = match.get("score", {}).get("fullTime", {}).get("homeTeam", "N/A")
    away_score = match.get("score", {}).get("fullTime", {}).get("awayTeam", "N/A")
    competition = match.get("competition", {}).get("name", "Unknown Competition")
    match_time = match.get("utcDate", "Unknown")

    if status == "FINISHED":
        return (f"Competition: {competition}\n"
                f"{home_team} vs {away_team}\n"
                f"Final Score: {home_score}-{away_score}\n"
                f"Date & Time: {match_time}\n")
    elif status == "IN_PLAY":
        return (f"Competition: {competition}\n"
                f"{home_team} vs {away_team}\n"
                f"Current Score: {home_score}-{away_score}\n"
                f"Match is in progress!\n")
    elif status == "SCHEDULED":
        return (f"Competition: {competition}\n"
                f"{home_team} vs {away_team}\n"
                f"Scheduled Time: {match_time}\n")
    else:
        return (f"Competition: {competition}\n"
                f"{home_team} vs {away_team}\n"
                f"Status: {status}\n")

def lambda_handler(event, context):
    api_key = os.getenv("FOOTBALL_API_KEY")
    sns_topic_arn = os.getenv("SNS_TOPIC_ARN")
    sns_client = boto3.client("sns")

    # Fetch today's matches
    today_date = datetime.now(timezone.utc).strftime("%Y-%m-%d")
    api_url = f"https://api.football-data.org/v4/matches?dateFrom={today_date}&dateTo={today_date}"
    headers = {"X-Auth-Token": api_key}

    print(f"Fetching football matches for {today_date}")
    data = fetch_football_data(api_url, headers)

    if not data or "matches" not in data:
        return {"statusCode": 500, "body": "Error fetching match data"}

    matches = data["matches"]
    messages = [format_match_data(match) for match in matches]
    final_message = "\n---\n".join(messages) if messages else "No matches available for today."

    # Publish to SNS
    try:
        sns_client.publish(
            TopicArn=sns_topic_arn,
            Message=final_message,
            Subject="Football Match Updates"
        )
        print("Message published to SNS successfully.")
    except Exception as e:
        print(f"Error publishing to SNS: {e}")
        return {"statusCode": 500, "body": "Error publishing to SNS"}

    return {"statusCode": 200, "body": "Football match data processed and sent to SNS"}

I added an environment variable so our function recognizes the API key and the SNS topic URL

Image description

3. Scheduling Lambda with EventBridge

  • Created a new EventBridge rule to trigger the Lambda function at specific times.

Image description

  • Configured it to run daily or at specific match times.

Image description

  • Linked the rule to the Lambda function.

Image description

Image description


Testing & Results

  • Deployed and tested the function manually.

Image description

  • Verified that SNS successfully delivered email notifications.

Image description


Future Improvements

  • Store match schedules in DynamoDB for historical data.
  • Extend notifications to SMS or mobile apps.
  • Create a User Interface

Conclusion

This project showcases how AWS services can be combined to build an automated notification system. By leveraging Lambda, SNS, and EventBridge, I’ve created a serverless solution that keeps users informed without manual effort.