Overview
Read this before the SNS hands-on lab, or any time you need to broadcast an event to multiple systems and want to understand the right tool and model.
The Problem SNS Solves
You've just processed a payment. Now three things need to happen:
- 1Send a confirmation email to the customer
- 2Update the invoice status in the audit service
- 3Trigger a fraud detection check
The naive approach, call each service directly from your payment service:
Payment Service
→ HTTP call → Email Service
→ HTTP call → Audit Service
→ HTTP call → Fraud DetectionThis works until it doesn't. Adding a fourth subscriber means changing the Payment Service. If Email Service is slow, payment processing slows. If Audit Service is down, the whole payment fails. Every subscriber is a dependency of the producer. SNS breaks this coupling:
Payment Service → SNS Topic → ├── Email Service
├── Audit Service
└── Fraud DetectionPayment Service publishes one message to the topic and returns. SNS delivers it to all subscribers simultaneously. Adding a fourth subscriber requires no change to the Payment Service, you just add a subscription. If Email Service is slow, it doesn't affect the others. This is fan-out: one event, many independent reactions.
What SNS Is
Amazon Simple Notification Service (SNS) is a fully managed pub/sub messaging service. A producer publishes a message to a topic. SNS immediately pushes that message to all subscribers of that topic. Key properties:
- Push-based: SNS delivers to subscribers. Subscribers don't poll.
- Fan-out: one publish, many deliveries simultaneously
- No persistence: SNS delivers immediately and moves on. If a subscriber is unavailable, the message is retried with backoff, but SNS is not a queue. It doesn't store messages for later consumption.
- Fully managed: no servers, no capacity planning
- Multiple protocol support: subscribers can be SQS queues, Lambda functions, HTTP/HTTPS endpoints, email addresses, SMS, or mobile push notifications
Core Concepts
Topic
A topic is the channel through which messages flow. Producers publish to a topic. Subscribers receive from a topic. A topic has an ARN: arn:aws:sns:ap-south-1:123456789:my-topic. Topics are either Standard (high throughput, best-effort ordering) or FIFO (strict ordering, exactly-once delivery, lower throughput, mirrors SQS FIFO).
Publisher
Any AWS service or application that calls Publish on the topic. One publisher, or many. Publishers don't know who the subscribers are.
Subscriber
An endpoint registered to receive messages from a topic. Supported subscriber types:
| Protocol | What receives the message | Use for |
|---|---|---|
| SQS | An SQS queue | Fan-out with persistence and independent processing |
| Lambda | A Lambda function invoked directly | Serverless event processing |
| HTTP/HTTPS | An HTTP endpoint (your API) | Webhooks to external services |
| An email address | Human notifications, alerts | |
| SMS | A phone number | Text message alerts |
| Mobile Push | iOS/Android push notification | Mobile app notifications |
| Firehose | Kinesis Data Firehose delivery stream | Streaming to S3, Redshift, OpenSearch |
Message
A message is a string up to 256KB. SNS wraps it in an envelope when delivering:
{
"Type": "Notification",
"MessageId": "abc-123",
"TopicArn": "arn:aws:sns:...",
"Message": "your actual payload here",
"Timestamp": "2024-01-25T10:00:00Z",
"Subject": "optional subject",
"MessageAttributes": {}
}The Message field is what you published. The envelope is added by SNS. Your subscriber receives the full envelope, you must parse it to get the original payload. This is a common source of confusion: SQS consumers reading from an SNS-subscribed queue receive the SNS envelope, not just the raw message.
The Delivery Model
Push, not pull
SNS pushes messages to subscribers. The moment you call Publish, SNS attempts delivery to every subscriber concurrently. Subscribers don't check in periodically. SNS comes to them.
Retry policy
For HTTP/HTTPS subscribers, SNS retries failed deliveries with exponential backoff. By default: 3 immediate retries, then 20 retries with delay up to 20 minutes, totalling 23 delivery attempts before giving up. For SQS and Lambda subscribers, the retry semantics are handled by those services (SQS visibility timeout, Lambda retry policy).
No persistence
SNS does not store messages. If all retries to a subscriber fail, the message is lost from SNS's perspective. This is why SNS → SQS is the standard pattern for anything that needs durability: SQS holds the message until the consumer confirms processing.
SNS vs SQS delivery guarantee
SQS guarantees every message is processed (it keeps the message until a consumer deletes it. SNS guarantees every message is *attempted*) it tries to deliver but doesn't keep the message. For critical workloads, always land SNS messages into an SQS queue, not directly into HTTP endpoints or Lambda, so you get both fan-out and durability.
Message Filtering
By default, every subscriber receives every message published to the topic. Message filtering lets subscribers declare which messages they care about, using filter policies on message attributes. Example: a payment topic publishes both successful and failed payments. The fraud detection service only cares about failures. The email service cares about both but sends different emails.
// Payment Service publishes with attributes:
{
"Message": "{\"paymentId\": \"PAY-001\", ...}",
"MessageAttributes": {
"status": {"DataType": "String", "StringValue": "FAILED"},
"amount": {"DataType": "Number", "StringValue": "149.99"}
}
}
// Fraud Detection subscription filter policy:
// Only receive messages where status = FAILED
{"status": ["FAILED"]}
// High-value transactions filter:
// Only receive messages where amount > 100
{"amount": [{"numeric": [">", 100]}]}SNS evaluates the filter policy before delivery. Messages that don't match are never delivered to that subscriber, they're not billed for it either. This keeps each subscriber's queue or Lambda clean, processing only the messages it cares about.
Filter policy scope: by default, filtering is on message attributes. You can also enable filtering on the message body (JSON), but this requires FilterPolicyScope: MessageBody.
SNS + SQS: Fan-out with Persistence
This is the most important SNS pattern. Used everywhere.
Event Producer
↓
SNS Topic
├──── SQS Queue A → Lambda / Worker (PDF generation)
├──── SQS Queue B → Lambda / Worker (Email sending)
└──── SQS Queue C → Lambda / Worker (Audit logging)Why SQS between SNS and the consumer, instead of SNS → Lambda directly?
- Durability: SQS holds the message if the Lambda is throttled, unavailable, or slow. SNS → Lambda directly means a Lambda throttle = message lost after retries.
- Rate control: SQS lets you control how fast Lambda processes (batch size, concurrency). SNS → Lambda directly invokes Lambda for every message immediately, a spike of 10,000 messages means 10,000 Lambda invocations at once.
- DLQ: SQS DLQ captures messages that repeatedly fail. SNS → Lambda has no equivalent capture mechanism.
- Independent scaling: each SQS queue drains at its own pace. PDF generation might take 5 seconds per message; email sending might take 50ms. They don't block each other.
The only reason to use SNS → Lambda directly (without SQS) is when you need the lowest possible latency and can tolerate message loss under Lambda throttling.
SNS Standard vs. FIFO
Standard Topic
- Best-effort ordering
- At-least-once delivery
- Unlimited throughput
- Subscribers: SQS Standard, Lambda, HTTP, email, SMS, mobile push, Firehose
FIFO Topic
- Strict ordering (within message group)
- Exactly-once delivery
- Up to 300 messages/sec (3,000 with batching)
- Subscribers: SQS FIFO only. No HTTP, email, Lambda directly.
- Use when the order of events is semantically meaningful, account created must be processed before account updated
Message Attributes vs. Message Body
Message attributes are metadata attached to a message, key-value pairs with a data type. They're used for:
- Filter policies (SNS reads attributes without parsing the body)
- Routing decisions
- Passing metadata without changing the payload schema
Message body is the actual content. SNS delivers it as a string. Structure it however you want (JSON is standard). Attributes are more efficient for filtering because SNS can evaluate them without deserialising the body.
SNS as an Alert System
SNS is the delivery mechanism for CloudWatch Alarms. When an alarm transitions to ALARM state, it publishes to an SNS topic. The topic delivers to email, SMS, Lambda, PagerDuty (via HTTPS), Slack (via Lambda), or any combination. This is the standard AWS alerting pattern:
CloudWatch Alarm → SNS Topic → ├─ Email (team)
├─ SMS (on-call)
└─ Lambda → PagerDuty / SlackYou've seen this in the CloudWatch Alarms lab. The SNS topic is the fan-out layer that lets one alarm notify multiple channels simultaneously.
SNS vs. SQS vs. EventBridge
| Dimension | SNS | SQS | EventBridge |
|---|---|---|---|
| Model | Pub/sub (push) | Queue (pull) | Event bus (push, rules-based) |
| Consumers per message | Many (all subscribers) | One | Many (matching rules) |
| Message persistence | No (retry only) | Yes (up to 14 days) | No (24h retry) |
| Filtering | Message attribute or body filter policies | None (all consumers see all messages) | Rich content-based rules (JSON pattern matching) |
| AWS service sources | Any publisher calls Publish API | Any producer calls SendMessage API | Native events from 200+ AWS services |
| Cross-account delivery | Yes (resource policy) | Yes (resource policy) | Yes (event bus to bus) |
Use SNS when: one event needs to go to multiple systems simultaneously, and you want simplicity. The fan-out pattern.
Use SQS when: one unit of work needs to be processed exactly once by one worker. The work queue pattern.
Use EventBridge when: you need content-based routing with complex rules, or you're reacting to events from AWS services (S3 object created, EC2 state change, etc.).
Subscription Confirmation
For HTTP/HTTPS and email subscribers, SNS requires subscription confirmation before delivering messages. When you create the subscription, SNS sends a confirmation request to the endpoint. The endpoint must respond by visiting a confirmation URL (email) or replying with the token (HTTP). This prevents SNS from being used to spam arbitrary endpoints. If you've set up billing alerts and wondered why emails didn't arrive, it's almost always an unconfirmed subscription. SQS and Lambda subscriptions don't require confirmation. IAM policy is sufficient.
Cost Model
- Free tier: 1 million publishes/month, 1,000 email deliveries/month, always free
- Publishes: $0.50 per million after free tier
- HTTP/HTTPS deliveries: $0.60 per million
- SQS deliveries: free (SQS charges apply separately)
- Lambda deliveries: free (Lambda charges apply separately)
- Email/SMS: email is cheap ($2/100k), SMS varies by country and carrier
- Data transfer: free within the same region
SNS is extremely cheap for the fan-out it provides. The cost is almost always dominated by the downstream services (SQS, Lambda) rather than SNS itself.
Summary
SNS is a megaphone. You speak once into it, and everyone who's listening hears you simultaneously.
It doesn't remember what you said, if someone wasn't listening, they missed it. For guaranteed delivery to each listener, put an SQS queue between SNS and each consumer. That's the SNS + SQS fan-out pattern, and it's the backbone of most event-driven architectures on AWS.