AWS Builder Center
Smart Notification Routing on AWS with SNS, Lambda, and CDK

Smart Notification Routing on AWS with SNS, Lambda, and CDK

Build a smart alert routing solution on AWS using Amazon SNS, AWS Lambda, and AWS CDK. Using SNS filter policies and message attributes, notifications are automatically routed based on team and severity levels (INFO, WARNING, CRITICAL). This serverless approach reduces infrastructure complexity while ensuring the right people receive the right alerts at the right time.

Software engineer | Data engineer | 8x AWS Certified

Introduction

When multiple teams and applications start sending alerts on AWS, managing notifications can quickly become messy. Creating separate SNS topics for every alert type, severity, or team often leads to duplicated configurations and infrastructure that becomes difficult to maintain over time.
In this project, we’ll build a simpler and more scalable solution using Amazon SNS filter policies, AWS Lambda, and AWS CDK. Instead of creating many SNS topics, we’ll use a single centralized topic and route alerts automatically based on attributes like severity (INFO, WARNING, CRITICAL) and team name.
The result is a clean serverless alerting system where developers only receive relevant alerts, while critical notifications can still be sent to everyone when needed.
We’ll show you how to do this in the following steps:
  • Step 1: Create the CDK project
  • Step 2: Install Project Dependencies
  • Step 3: Create the SNS Topic and Subscriptions
  • Step 4: Create the Lambda Publisher Function
  • Step 5: Add the Lambda Function to the CDK Stack
  • Step 6: Configure the CDK Application Entry Point
  • Step 7: Bootstrap and Deploy the Infrastructure
  • Step 8: Test the Alert Routing System



Architecture

The AWS solution we are building provides:
  • Operational Excellence: This solution improves operational excellence by centralizing alert management and automating notification routing using SNS filter policies. Using AWS CDK also enables consistent and repeatable infrastructure deployments.
  • Performance Efficiency: Using lightweight serverless services allows the solution to scale automatically based on alert traffic. SNS filter policies also reduce unnecessary notifications and processing overhead.
  • Cost Optimization: A centralized SNS topic reduces infrastructure complexity and avoids creating multiple topics for every alert type. Since the solution is fully serverless, costs remain low with pay-per-use pricing.
Here’s an architecture diagram of what we’ll implement:
Architecture diagram




Key concepts

Before beginning the practical steps, let’s understand the main AWS services and concepts used in this solution.
  • SNS Filter Policies: SNS filter policies allow subscriptions to receive only specific messages based on message attributes. Instead of creating multiple SNS topics, we can use a single topic and automatically route alerts depending on attributes such as severity, team, or environment.
  • Message Attributes: Message attributes are metadata attached to SNS messages. In this solution, attributes like severity=CRITICAL or team=dev are used by SNS filter policies to determine which subscribers should receive each alert.
  • AWS CDK: AWS Cloud Development Kit (CDK) is an Infrastructure as Code (IaC) framework that allows AWS resources to be defined using programming languages such as Python. We will use CDK to provision the SNS topic, subscriptions, filter policies, and Lambda function.
Now that we’ve covered the core components, let’s see how they all fit together.



Steps

Step 1: Create the CDK Project

In this step, we initialize a new AWS CDK application using Python. This project will contain all the infrastructure code required to deploy the SNS topic, Lambda function, subscriptions, and filter policies. Organizing the project from the beginning helps keep the infrastructure modular and easier to maintain as the solution grows.
Bash
mkdir alerting-system
cd alerting-system

cdk init app --language python
Output:
AWS CLI: CDK init app command

After running the command, the following folders are created:
plaintext
+---alerting-system
| | .gitignore
| | app.py
| | cdk.json
| | README.md
| | requirements-dev.txt
| | requirements.txt
| | source.bat
| |
| +---alerting_system
| | alerting_system_stack.py
| | __init__.py
| |
| \---tests
| | __init__.py
| |
| \---unit
| test_alerting_system_stack.py
| __init__.py
|



Step 2: Install Project Dependencies

Before writing any infrastructure code, we need to install the AWS CDK libraries and required Python packages. These dependencies provide the constructs and modules used to define AWS resources programmatically.
Run the following command to install dependencies:
Bash
pip install aws-cdk-lib constructs
Output:
AWS CLI: Run PIP install




Step 3: Create the SNS Topic and Subscriptions

Here, we create a centralized SNS topic that will handle all alerts in the system. We also configure email subscriptions with SNS filter policies so that notifications are routed only to the appropriate recipients based on attributes like severity or team name. For the filter policies, we want developers to receive all notifications regardless of their severity ("INFO", "WARNING", or "CRITICAL"). As long as the message contains the attribute "team=dev", it should be delivered to the development team. For the rest of the stakeholders, such as Operations and Managers, we only want to notify them when immediate attention is required. To achieve this, we'll configure a filter policy that only delivers messages where the "severity" attribute is set to "CRITICAL".
Create stacks/alerts_stack.py
Python
from aws_cdk import (
Stack,
aws_sns as sns,
aws_sns_subscriptions as subs,
)

from constructs import Construct

class AlertsStack(Stack):

def __init__(
self,
scope: Construct,
construct_id: str,
developer_emails: list[str],
everyone_emails: list[str],
**kwargs
):
super().__init__(scope, construct_id, **kwargs)

alerts_topic = sns.Topic(
self,
"CentralAlertsTopic",
topic_name="central-alerts-topic"
)

# Developers subscription
for email in developer_emails:

alerts_topic.add_subscription(
subs.EmailSubscription(
email,

filter_policy={
"team": sns.SubscriptionFilter.string_filter(
allowlist=["dev"]
)
}
)
)

# Everyone receives CRITICAL alerts
for email in everyone_emails:

alerts_topic.add_subscription(
subs.EmailSubscription(
email,

filter_policy={
"severity": sns.SubscriptionFilter.string_filter(
allowlist=["CRITICAL"]
)
}
)
)



Step 4: Create the Lambda Publisher Function

In this step, we build the Lambda function responsible for publishing messages to the SNS topic. The function receives alert details such as severity, environment, and team, then attaches them as SNS message attributes for filtering and routing.
Create Lambda Directory
Bash
mkdir -p lambda/publisher
Create lambda/publisher/handler.py
Python
import os
import json
import boto3
from botocore.exceptions import ClientError

sns = boto3.client("sns")

TOPIC_ARN = os.environ["TOPIC_ARN"]

def lambda_handler(event, context):
try:
response = sns.publish(
TopicArn=TOPIC_ARN,
Subject=event["subject"],
Message=event["message"],
MessageAttributes={
"severity": {
"DataType": "String",
"StringValue": event["severity"]
},
"team": {
"DataType": "String",
"StringValue": event["team"]
},
"environment": {
"DataType": "String",
"StringValue": event["environment"]
}
}
)

return {
"statusCode": 200
}
except ClientError as e:
print(f"SNS publish failed: {e}")

return {
"statusCode": 500,
"body": json.dumps({
"error": str(e)
})
}

except Exception as e:
print(f"Unexpected error: {e}")

return {
"statusCode": 500,
"body": json.dumps({
"error": "Unexpected error occurred"
})
}



Step 5: Add the Lambda Function to the CDK Stack

Now we need to connect the Lambda function to the infrastructure stack and grant it permission to publish messages to the SNS topic.
Update stacks/alerts_stack.py
Python
from aws_cdk import (
Stack,
aws_sns as sns,
aws_sns_subscriptions as subs,
Duration,
aws_lambda as _lambda,
)

from constructs import Construct

class AlertsStack(Stack):

…

# Lambda function to publish alerts
publisher_lambda = _lambda.Function(
self,
"AlertsPublisherLambda",

runtime=_lambda.Runtime.PYTHON_3_12,

handler="handler.lambda_handler",

code=_lambda.Code.from_asset(
"lambda/publisher"
),

timeout=Duration.seconds(30),

environment={
"TOPIC_ARN": alerts_topic.topic_arn
}
)
# Grant the Lambda function permissions to publish to the SNS topic
alerts_topic.grant_publish(
publisher_lambda
)



Step 6: Configure the CDK Application Entry Point

The CDK application entry point connects all infrastructure components together. This file initializes the stack and prepares the project for synthesis and deployment into the AWS account.
Update app.py
Python
#!/usr/bin/env python3

import aws_cdk as cdk

from stacks.alerts_stack import AlertsStack

app = cdk.App()

developer_emails = (
app.node.try_get_context("developerEmails")
or "developer@example.com"
).split(",")

everyone_emails = (
app.node.try_get_context("everyoneEmails")
or "everyone@example.com"
).split(",")

AlertsStack(
app,
"AlertsStack",
developer_emails=developer_emails,
everyone_emails=everyone_emails
)

app.synth()



Step 7: Bootstrap and Deploy the Infrastructure

Before deploying CDK applications for the first time, AWS requires a bootstrap process. After bootstrapping, we can deploy the entire serverless alerting solution directly from the terminal. This creates:
  • S3 bucket for CDK assets
  • IAM roles for deployments
  • CloudFormation stack
  1. Bootstrap AWS Environment:
Bash
cdk bootstrap
 Output:
AWS CLI: CDK Bootstrap Command

From the Console, a new Cloudformation stack was created:
AWS Console: Cloudformation Stacks- CDKToolkit

  1. Deploy the Stack:
Bash
cdk deploy \
-c developerEmails=dev1@example.com,dev2@example.com \
-c everyoneEmails=all@example.com,manager@example.com
Output:
AWS CLI: CDK deploy command

After deployment, SNS will send email confirmation links to subscribers. The email subscription requires the recipient to click a confirmation link. Until confirmed, the subscription remains in a pending state.
>> Result: The developers and the manager, will all receive the following email
AWS Notification : Subscription Confirmation Email




Step 8: Test the Alert Routing System

Finally, we test the solution by invoking the Lambda function with different alert payloads. This validates that SNS filter policies are correctly routing notifications based on message attributes.
  • Test CRITICAL Alert
Note update the function-name from what the CDK generated
Bash
aws lambda invoke \
--function-name AlertsStack-AlertsPublisherLambda \
--cli-binary-format raw-in-base64-out \
--payload '{
"subject":"Production Outage",
"message":"Payments API is down",
"severity":"CRITICAL",
"team":"dev",
"environment":"prod"
}' \
response.json
 Output:
AWS CLI: Invoke the lambda function to notify all the subscribers including the dev team

>> Result: All the subscribers received this email
Email Inbox: New SNS Notification Received Successfully

  • Test Dev Alert
Bash
aws lambda invoke \
--function-name AlertsStack-AlertsPublisherLambda \
--cli-binary-format raw-in-base64-out \
--payload '{
"subject":"ETL Completed",
"message":"Daily ETL succeeded",
"severity":"INFO",
"team":"dev",
"environment":"prod"
}' \
response.json
Output:
AWS CLI: Invoke the lambda function to notify the dev team only

>> Result: Only dev team received this email notifications
Email Inbox: New SNS Notification Received Successfully




Conclusion

In this article, we built a smart alert routing solution using AWS Lambda, Amazon SNS, SNS filter policies, and AWS CDK. By using a single SNS topic and message attributes, we were able to route notifications to the right audience based on severity and team, while keeping the architecture simple and scalable.
This approach reduces infrastructure complexity, lowers operational overhead, and provides a flexible foundation that can easily be extended as notification requirements grow.



References

Any opinions in this article are those of the individual author and may not reflect the opinions of AWS.
Enjoyed reading this content? Let the author know!

Your likes, comments, shares, and saves help creators reach more builders.

Loading recommendations

Loading article