AWS CDK Lambda Uptime Monitoring

After building and deploying my first AWS CDK project—a simple Lambda function and S3 bucket—I wanted to push the concept further.

The initial project taught me how to:

  • Package and deploy Python-based Lambda functions
  • Use AWS CDK to synthesize and deploy CloudFormation templates
  • Handle IAM access securely (without using root credentials)
  • Debug real-world issues like Lambda bundling and deployment errors

Building upon that foundation, I created a Serverless Uptime Checker that:

  • Monitors websites every 5 minutes using an AWS Lambda triggered by EventBridge
  • Logs uptime data to CloudWatch Logs
  • Sends optional email alerts via SNS when a site becomes unreachable

This project demonstrates practical DevOps skills in automation, observability, and cloud infrastructure, using fully managed, serverless AWS services.

Skills Demonstrated:

  • Infrastructure as Code (IaC): Provisioned cloud resources using AWS CDK and Python
  • Monitoring and Observability: Built an automated uptime checker using AWS Lambda, Amazon EventBridge, CloudWatch Logs and Alarms, and SNS
  • Secure Parameterization & IAM: Passed sensitive values at deploy time via CDK Parameters and applied least-privilege IAM permissions

Prerequisites:

  • AWS account with programmatic access (via IAM user or role)
  • AWS CLI: Install AWS CLI
  • Python 3.8+
  • Node.js (v14 or later) and NPM (for CDK CLI dependencies): https://nodejs.org/en
  • AWS CDK v2: npm install -g aws-cdk
  • (Optional) Python virtual environment tool like venv for dependency isolation

Project Setup

Project Initialization

Create and initialize your AWS CDK app:

mkdir uptime-checker && cd uptime-checker
    cdk init app --language python
    

(Optional) Set up a Python virtual environment:

python -m venv .venv
    source .venv/bin/activate   # For Windows: .venv\Scripts\activate
    

After running this command, your project directory should now look like this:

uptime-checker/
    ├── README.md
    ├── app.py
    ├── cdk.json
    ├── uptime_checker/
    │   ├── __init__.py
    │   └── uptime_checker_stack.py
    ├── lambda/
    │   ├── __init__.py
    │   └── lambda_function.py
    ├── requirements.txt
    ├── .gitignore
    └── .venv/  (optional, virtual environment)
    

Install Dependencies

Update requirements.txt to include:

aws-cdk-lib==2.x.x
    constructs>=10.0.0,<11.0.0
    requests
    

Then install dependencies:

pip install -r requirements.txt
    

Write Your Lambda Function

The Lambda function lambda/lambda_function.py reads a list of websites from an environment variable (WEBSITES_JSON), checks each URL, and logs whether the site is up, down, or returning an error status.

import os, json, requests
    from datetime import datetime, timezone

    WEBSITES = json.loads(os.environ['WEBSITES_JSON'])

    def lambda_handler(event, context):
        timestamp = datetime.now(timezone.utc).isoformat()
        for site in WEBSITES:
            name, url = site['name'], site['url']
            try:
                resp = requests.get(url, timeout=5)
                status = "Up" if resp.status_code == 200 else f"Error {resp.status_code}"
            except requests.RequestException:
                status = "Down"
            print(f"{timestamp} | {name} ({url}) → {status}")
        return {'statusCode': 200}
    

Define Your Infrastructure Stack

This CDK stack uptime_checker/uptime_checker_stack.py defines the serverless infrastructure for your uptime checker by setting up:

  • A Lambda function to check site status
  • An EventBridge rule to run the Lambda every 5 minutes
  • An environment variable (WEBSITES_JSON) to pass monitored URLs securely
from aws_cdk import (
        Stack,
        Duration,
        aws_lambda as _lambda,
        aws_events as events,
        aws_events_targets as targets,
    )
    from constructs import Construct
    import json

    class UptimeCheckerStack(Stack):

        def __init__(self, scope: Construct, construct_id: str, **kwargs):
            super().__init__(scope, construct_id, **kwargs)

            websites = [
                {"name": "Portfolio", "url": "https://portfolio-4wj.pages.dev/"},
                {"name": "TrustScience", "url": "https://trustscience.com"}
            ]

            fn = _lambda.Function(
                self, "UptimeCheckFn",
                runtime=_lambda.Runtime.PYTHON_3_10,
                handler="lambda_function.lambda_handler",
                code=_lambda.Code.from_asset("lambda"),
                environment={
                    "WEBSITES_JSON": json.dumps(websites)
                },
                timeout=Duration.seconds(10)
            )

            events.Rule(
                self, "5MinRule",
                schedule=events.Schedule.rate(Duration.minutes(5)),
                targets=[targets.LambdaFunction(fn)]
            )
    

Tip: For better flexibility, you can make the monitored websites configurable via environment variables, CDK context, or SSM Parameters.

Adding Email Alerts via SNS + CloudWatch Alarm (Secure & Parameterized)

To extend the functionality of our uptime checker with notifications, we will add:

  • An SNS Topic to publish alerts
  • An email subscription, passed as a CDK parameter
  • A CloudWatch Alarm that triggers when the Lambda function records errors

Step 1: Update Your Stack (uptime_checker_stack.py)

from aws_cdk import (
        Duration,
        Stack,
        aws_lambda as _lambda,
        aws_events as events,
        aws_events_targets as targets,
        aws_logs as logs,
        aws_sns as sns,
        aws_sns_subscriptions as subs,
        aws_cloudwatch as cw,
        aws_cloudwatch_actions as cw_actions,
        CfnParameter,
    )
    from constructs import Construct
    import json

    class UptimeCheckerStack(Stack):

        def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
            super().__init__(scope, construct_id, **kwargs)

            # sns topic + email subscription
            alert_email = CfnParameter(self, "AlertEmail", type="String", description="email for SNS alerts")
            topic = sns.Topic(self, "UptimeAlertsTopic")
            topic.add_subscription(subs.EmailSubscription(alert_email.value_as_string))

            websites = [
                {"name": "Portfolio", "url": "https://portfolio-4wj.pages.dev/"},
                {"name": "TrustScience", "url": "https://trustscience.com"}
            ]

            check_fn = _lambda.Function(
                self, "CheckFn",
                runtime=_lambda.Runtime.PYTHON_3_10,
                handler="lambda_function.lambda_handler",
                code=_lambda.Code.from_asset("lambda"),
                environment={
                    "WEBSITES_JSON": json.dumps(websites)
                },
                timeout=Duration.seconds(10),
                log_retention=logs.RetentionDays.ONE_DAY,
            )

            events.Rule(
                self, "5MinRule",
                schedule=events.Schedule.rate(Duration.minutes(5)),
                targets=[targets.LambdaFunction(check_fn)]
            )

            # CloudWatch alarm: trigger if errors >= 1 in 5min window
            error_metric = check_fn.metric_errors(
                period=Duration.minutes(5),
                statistic="Sum"
            )

            alarm=cw.Alarm(self, "LambdaErrorAlarm",
                    metric=error_metric,
                    threshold=1,
                    evaluation_periods=1,
                    datapoints_to_alarm=1,
                    treat_missing_data=cw.TreatMissingData.NOT_BREACHING,
                    alarm_description="Uptime Lambda error",
                    )
            alarm_action = cw_actions.SnsAction(topic)
            alarm.add_alarm_action(alarm_action)
    

Step 2: Deploy With Email Parameter

Deploy your stack and specify your email address to receive alerts:

cdk deploy --parameters AlertEmail=<your-email@example.com>
    

Note: You’ll receive a confirmation email from AWS SNS. You must click the confirmation link to activate alerts.

Security Notes

  • Your email is never hardcoded in the source code; instead, it is passed securely at deploy time and not stored in version control
  • For shared or team environments, consider using AWS SSM Parameters Store instead

Test Uptime Checker:

  • Verify Lambda execution by checking CloudWatch Logs for the UptimeCheckFn log group. Review recent log entries to see uptime check results with timestamps.
  • Simulate a failure (e.g., invalid URL) and verify you receive an email alert triggered by the CloudWatch alarm.

Next Steps:

This project is a great base to build upon. Here are some optional next steps:

  • Add persistent storage (e.g., DynamoDB or S3) for historical uptime data
  • Create HTML reports or dashboards
  • Integrate alerts with Slack or other channels using AWS Chatbot
  • Automate deployments with CI/CD pipelines (e.g., GitHub Actions)
  • Add custom CloudWatch metrics for response times

Happy Monitoring!