SNS, SQS, and EventBridge
Messaging services decouple producers from consumers — instead of Service A calling Service B directly, it sends a message that Service B picks up later. This makes systems more resilient, scalable, and easier to evolve.
Overview
Section titled “Overview”| Service | Model | Pattern | Use Case |
|---|---|---|---|
| SQS | Queue | Point-to-point | Worker processing, task queues, buffering |
| SNS | Pub/Sub | Fan-out (one-to-many) | Notifications, broadcasting events to multiple consumers |
| EventBridge | Event bus | Event routing with rules | Event-driven architectures, cross-service integration, SaaS events |
Producer ──► SQS Queue ──► Single Consumer (pull)
Producer ──► SNS Topic ──► Consumer A ──► Consumer B (fan-out) ──► Consumer C
Producer ──► EventBridge ──► Rule 1 ──► Lambda ──► Rule 2 ──► SQS Queue (content-based routing) ──► Rule 3 ──► Step FunctionsSQS (Simple Queue Service)
Section titled “SQS (Simple Queue Service)”SQS is a fully managed message queue. Producers send messages; consumers poll and process them.
Queue Types
Section titled “Queue Types”| Standard Queue | FIFO Queue | |
|---|---|---|
| Ordering | Best-effort (mostly ordered) | Guaranteed first-in-first-out |
| Delivery | At-least-once (possible duplicates) | Exactly-once processing |
| Throughput | Nearly unlimited | 300 msg/s (3,000 with batching) |
| Use case | High-throughput work where order doesn’t matter | Financial transactions, order processing |
How SQS Works
Section titled “How SQS Works”Producer ──send──► [ msg3 msg2 msg1 ] ──receive──► Consumer SQS Queue │ ▼ process msg1 │ delete msg1- Producer sends a message to the queue.
- Consumer receives (polls) a message — the message becomes invisible to other consumers.
- Consumer processes the message.
- Consumer deletes the message from the queue.
- If the consumer fails (doesn’t delete within the visibility timeout), the message reappears for retry.
Key Settings
Section titled “Key Settings”| Setting | What It Does | Default |
|---|---|---|
| Visibility timeout | How long a received message is hidden from other consumers | 30 seconds |
| Message retention | How long unprocessed messages are kept | 4 days (max 14) |
| Receive wait time | Long polling wait (0 = short polling, 1–20s = long polling) | 0 (short) |
| Delay seconds | Delay before a new message becomes visible | 0 |
| Max message size | Maximum message body | 256 KB |
Always use long polling (ReceiveWaitTimeSeconds: 20) — it reduces empty responses and API costs.
Dead-Letter Queues (DLQ)
Section titled “Dead-Letter Queues (DLQ)”A DLQ catches messages that fail processing repeatedly:
Main Queue ──► Consumer fails 3 times ──► Dead-Letter Queue │ ▼ Investigate and fix# Create a DLQaws sqs create-queue --queue-name orders-dlq
# Set DLQ on the main queue (after 3 failed receives)aws sqs set-queue-attributes --queue-url https://sqs.../orders \ --attributes '{ "RedrivePolicy": "{\"deadLetterTargetArn\":\"arn:aws:sqs:us-east-1:123456789012:orders-dlq\",\"maxReceiveCount\":\"3\"}" }'SQS + Lambda
Section titled “SQS + Lambda”Lambda can poll SQS automatically — no need to write polling code:
aws lambda create-event-source-mapping \ --function-name process-orders \ --event-source-arn arn:aws:sqs:us-east-1:123456789012:orders \ --batch-size 10Lambda scales up consumers based on queue depth.
Python Example
Section titled “Python Example”import boto3, json
sqs = boto3.client('sqs')queue_url = 'https://sqs.us-east-1.amazonaws.com/123456789012/orders'
# Sendsqs.send_message( QueueUrl=queue_url, MessageBody=json.dumps({'order_id': 123, 'amount': 49.99}), MessageAttributes={ 'priority': {'DataType': 'String', 'StringValue': 'high'} })
# Receive and processresponse = sqs.receive_message( QueueUrl=queue_url, MaxNumberOfMessages=10, WaitTimeSeconds=20 # long polling)for msg in response.get('Messages', []): body = json.loads(msg['Body']) process_order(body) sqs.delete_message(QueueUrl=queue_url, ReceiptHandle=msg['ReceiptHandle'])SNS (Simple Notification Service)
Section titled “SNS (Simple Notification Service)”SNS is a pub/sub service — a producer publishes a message to a topic, and all subscribers receive it.
How SNS Works
Section titled “How SNS Works”Publisher ──publish──► SNS Topic ──► SQS Queue (subscriber) ──► Lambda (subscriber) ──► Email (subscriber) ──► HTTP endpoint (subscriber)Subscriber Types
Section titled “Subscriber Types”| Type | Use Case |
|---|---|
| SQS | Fan-out to queues for async processing |
| Lambda | Trigger serverless functions |
| HTTP/HTTPS | Webhook to external services |
| Notifications to humans | |
| SMS | Text message alerts |
| Kinesis Firehose | Stream events to S3, Redshift, etc. |
SNS + SQS Fan-Out Pattern
Section titled “SNS + SQS Fan-Out Pattern”The most common pattern — one event triggers multiple independent processors:
Order placed ──► SNS Topic: order-events ├──► SQS: payment-queue ──► Payment service ├──► SQS: inventory-queue ──► Inventory service ├──► SQS: notification-queue ──► Email service └──► Lambda: analytics ──► Write to data lakeEach consumer gets its own copy of every message and processes independently.
Message Filtering
Section titled “Message Filtering”Subscribers can filter messages by attributes — receive only what they care about:
{ "event_type": ["order_placed"], "region": ["us-east", "us-west"]}Only messages matching the filter are delivered to that subscriber.
Creating a Topic and Publishing
Section titled “Creating a Topic and Publishing”# Create topicaws sns create-topic --name order-events
# Subscribe an SQS queueaws sns subscribe --topic-arn arn:aws:sns:...:order-events \ --protocol sqs --notification-endpoint arn:aws:sqs:...:payment-queue
# Publishaws sns publish --topic-arn arn:aws:sns:...:order-events \ --message '{"order_id": 123, "amount": 49.99}' \ --message-attributes '{"event_type":{"DataType":"String","StringValue":"order_placed"}}'SNS FIFO Topics
Section titled “SNS FIFO Topics”Like SQS FIFO — guaranteed ordering and deduplication. FIFO topics can only publish to FIFO SQS queues.
EventBridge
Section titled “EventBridge”EventBridge is an event bus that routes events based on rules and patterns. It’s the most flexible option — think of it as SNS with content-based routing and native AWS service integration.
How EventBridge Works
Section titled “How EventBridge Works”Event Source ──► Event Bus ──► Rule (pattern match) ──► Target Rule ──► Target Rule ──► TargetEvent Structure
Section titled “Event Structure”Every EventBridge event is a JSON envelope:
{ "version": "0", "id": "abc-123", "source": "com.myapp.orders", "detail-type": "OrderPlaced", "time": "2026-02-16T10:30:00Z", "region": "us-east-1", "account": "123456789012", "detail": { "order_id": 123, "amount": 49.99, "customer_id": "cust_456" }}Rules and Patterns
Section titled “Rules and Patterns”Rules match events by content and route them to targets:
{ "source": ["com.myapp.orders"], "detail-type": ["OrderPlaced"], "detail": { "amount": [{"numeric": [">", 100]}] }}This rule matches only OrderPlaced events where amount > 100.
Targets
Section titled “Targets”| Target | Use Case |
|---|---|
| Lambda | Process the event |
| SQS | Buffer for async processing |
| Step Functions | Start a workflow |
| SNS | Fan-out to subscribers |
| Kinesis | Stream processing |
| API Gateway | Call an HTTP API |
| ECS task | Run a container |
| CloudWatch Logs | Log events for debugging |
| Another event bus | Cross-account or cross-region routing |
Publishing Custom Events
Section titled “Publishing Custom Events”import boto3, json
events = boto3.client('events')
events.put_events(Entries=[{ 'Source': 'com.myapp.orders', 'DetailType': 'OrderPlaced', 'Detail': json.dumps({ 'order_id': 123, 'amount': 49.99, 'customer_id': 'cust_456' }), 'EventBusName': 'default'}])AWS Service Events
Section titled “AWS Service Events”Many AWS services publish events to EventBridge automatically:
| Service | Example Event |
|---|---|
| EC2 | Instance state change (running → stopped) |
| ECS | Task state change |
| S3 | Object created (via EventBridge notification) |
| CodePipeline | Pipeline execution state change |
| Health | AWS service health events |
| GuardDuty | Security findings |
{ "source": ["aws.ec2"], "detail-type": ["EC2 Instance State-change Notification"], "detail": { "state": ["terminated"] }}Scheduled Events
Section titled “Scheduled Events”EventBridge replaces CloudWatch Events for cron-like schedules:
# Run a Lambda every houraws events put-rule --name hourly-cleanup \ --schedule-expression "rate(1 hour)"
# Cron: weekdays at 9 AM UTCaws events put-rule --name daily-report \ --schedule-expression "cron(0 9 ? * MON-FRI *)"When to Use Which
Section titled “When to Use Which”| Scenario | Use |
|---|---|
| Simple task queue (one producer → one consumer) | SQS |
| Fan-out one event to multiple consumers | SNS + SQS |
| Content-based routing (different events → different targets) | EventBridge |
| React to AWS service events | EventBridge |
| Cron / scheduled tasks | EventBridge |
| High-throughput, order-sensitive | SQS FIFO |
| Email / SMS notifications | SNS |
| Complex event-driven microservices | EventBridge |
Key Takeaways
Section titled “Key Takeaways”- SQS is a queue (point-to-point). Use for task processing, buffering, and decoupling. Always enable long polling and set up a dead-letter queue.
- SNS is pub/sub (fan-out). Use with SQS for the fan-out pattern — one event triggers multiple independent consumers.
- EventBridge is an event bus with content-based routing. Use for event-driven architectures, AWS service events, and scheduled tasks.
- All three integrate natively with Lambda — no polling code needed.
- SNS + SQS fan-out is the most common pattern: SNS broadcasts, each SQS queue buffers for its consumer.