Documentation Index
Fetch the complete documentation index at: https://docs.ahmadraza.in/llms.txt
Use this file to discover all available pages before exploring further.
Quick Reference: How SNS Works with Lambda for Slack Notifications
π― The Simple Version
What Happens When an Alarm Triggers?
1. RDS CPU hits 85% for 15 minutes
β
2. CloudWatch Alarm: "CW-RDS-AppName-prod-rds-db-CPUUtilization" β ALARM state
β
3. Alarm has this config: alarm_actions = ["arn:aws:sns:...:PROD_Default_CloudWatch_Alarms_Topic"]
β
4. SNS Topic receives the alarm notification
β
5. SNS sees: "I have a Lambda subscriber for this topic!"
β
6. SNS invokes Lambda: CloudWatch-Alarms-To-Slack
β
7. Lambda receives SNS event, parses the alarm data
β
8. Lambda formats a pretty message with colors & emojis
β
9. Lambda sends HTTP POST to Slack webhook
β
10. π¬ Message appears in your Slack channel!
π Key Concepts
SNS (Simple Notification Service)
- Think of it as: A message router/broadcaster
- What it does: When it receives a message, it forwards it to all subscribers
- Subscribers can be: Lambda, Email, SMS, HTTP endpoints, etc.
- In our case: CloudWatch β SNS β Lambda
Why use SNS instead of CloudWatch β Lambda directly?
β
Flexibility: You can add multiple subscribers (email, Lambda, etc.)
β
Decoupling: CloudWatch doesnβt need to know about Lambda
β
Fan-out: One alarm can notify multiple destinations
β
Retry logic: SNS handles retries if Lambda fails
Lambda Subscription to SNS
resource "aws_sns_topic_subscription" "lambda_subscription" {
topic_arn = "arn:aws:sns:ap-south-1:3AWS-Account-ID-NO5:PROD_Default_CloudWatch_Alarms_Topic"
protocol = "lambda" # β This tells SNS: "Call a Lambda function"
endpoint = aws_lambda_function.slack_notifier.arn # β This Lambda
}
This creates a subscription that says:
βHey SNS topic! Whenever you receive a message, please invoke this Lambda functionβ
Permission for SNS to Call Lambda
resource "aws_lambda_permission" "allow_sns" {
statement_id = "AllowExecutionFromSNS"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.slack_notifier.function_name
principal = "sns.amazonaws.com" # β SNS service
source_arn = var.sns_topic_arn # β Only this specific SNS topic
}
This permission says:
βLambda function, please allow SNS to invoke youβ
π Data Flow Example
CloudWatch Alarm Data
{
"AlarmName": "CW-RDS-AppName-prod-rds-db-CPUUtilization",
"NewStateValue": "ALARM",
"NewStateReason": "Threshold Crossed: 3 datapoints were greater than threshold",
"Region": "ap-south-1",
"Trigger": {
"MetricName": "CPUUtilization",
"Namespace": "AWS/RDS",
"Threshold": 80.0
}
}
SNS Wraps it
{
"Records": [
{
"Sns": {
"Type": "Notification",
"TopicArn": "arn:aws:sns:ap-south-1:3AWS-Account-ID-NO5:PROD_Default_CloudWatch_Alarms_Topic",
"Message": "{...CloudWatch alarm JSON above...}",
"Timestamp": "2026-01-12T10:30:00.000Z"
}
}
]
}
Lambda Receives & Processes
def lambda_handler(event, context):
# Extract the CloudWatch alarm from SNS wrapper
sns_record = event['Records'][0]['Sns']
alarm_data = json.loads(sns_record['Message'])
# alarm_data now has: AlarmName, NewStateValue, etc.
# Format for Slack
slack_message = {
"text": f"π¨ {alarm_data['AlarmName']} is in {alarm_data['NewStateValue']} state"
}
# Send to Slack
requests.post(SLACK_WEBHOOK_URL, json=slack_message)
Slack Receives
π¨ CloudWatch Alarm: ALARM
ββββββββββββββββββββββββββββββββ
π Alarm Name: CW-RDS-AppName-prod-rds-db-CPUUtilization
π State Change: OK β ALARM
π Reason: Threshold Crossed: 3 datapoints...
πͺ All Components Working Together
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β YOUR AWS ACCOUNT β
β β
β βββββββββββββββββββ β
β β RDS Instance β CPU at 85% β
β β AppName-prod-rds β β
β ββββββββββ¬βββββββββ β
β β β
β β CloudWatch monitors metrics β
β βΌ β
β βββββββββββββββββββ β
β β CloudWatch β Threshold breached! β
β β Alarm β β
β ββββββββββ¬βββββββββ β
β β β
β β alarm_actions = [SNS Topic ARN] β
β βΌ β
β βββββββββββββββββββ β
β β SNS Topic β Receives alarm notification β
β β PROD_Default_ β β
β β CloudWatch_ β Has subscribers: β
β β Alarms_Topic β - Lambda function β
β ββββββββββ¬βββββββββ β
β β β
β β Invokes all subscribers β
β βΌ β
β βββββββββββββββββββ β
β β Lambda Function β 1. Receives SNS event β
β β CloudWatch- β 2. Parses alarm data β
β β Alarms-To-Slack β 3. Formats message β
β β β 4. HTTP POST to Slack β
β ββββββββββ¬βββββββββ β
β β β
βββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββ
β
β HTTPS POST request
β with formatted JSON
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β SLACK β
β β
β βββββββββββββββββββ β
β β Your Channel β π¬ Message appears! β
β β #alerts or β β
β β #cloudwatch β π¨ CW-RDS-AppName-prod-rds-db... β
β βββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
π Why This Architecture?
Alternative 1: CloudWatch β Lambda directly
β Not supported by AWS (CloudWatch canβt directly invoke Lambda for alarms)
β Would need custom EventBridge rules (more complex)
Alternative 2: CloudWatch β Email
β Not pretty, just plain text
β No formatting or colors
β Hard to filter/organize
Our Solution: CloudWatch β SNS β Lambda β Slack
β
Standard AWS pattern (SNS is designed for this)
β
Flexible (can add email, SMS, etc. to SNS later)
β
Pretty Slack messages with formatting
β
Easy to customize Lambda code
β
Reliable (SNS handles retries)
π Summary
SNS is the glue that connects CloudWatch alarms to Lambda functions.
Think of SNS as a notification hub:
- CloudWatch says: βHey SNS, I have an alarm!β
- SNS says: βThanks! Let me notify all my subscribersβ
- Lambda (as subscriber) says: βGot it! Sending to Slackβ¦β
Without SNS, youβd need complex EventBridge rules and more configuration.
With SNS, itβs a simple, standard AWS pattern that works reliably.
π Ready to Deploy?
Run these commands:
# 1. Validate
terraform validate
# 2. Preview what will be created
terraform plan
# 3. Deploy
terraform apply
# 4. Test
aws lambda invoke \
--function-name CloudWatch-Alarms-To-Slack \
--payload file://test-event.json \
output.json
Your alarms will automatically flow through this pipeline:
CloudWatch β SNS β Lambda β Slack π