Engineering Notes
Home/DevOps & Cloud/AWS/SQS and SNS
DevOps & Cloud · AWS

SQS and SNS

SQS queues work for consumers to pull; SNS pushes notifications to many subscribers. Watch the visibility timeout make SQS at-least-once, compare Standard vs FIFO, and build the SNS → SQS fan-out pattern.

☁️ DevOps & Cloud● Intermediate⏱ 4 min read▶ 2 interactive🛠️ 3 exercises🎤 5 interview Q&As

🎯 What you'll learn

  • SQS basics: visibility timeout, long polling, DLQ redrive
  • Standard vs FIFO queues
  • SNS topics, subscriptions and filtering
  • Fan-out, and Lambda vs worker consumers

📚 Before you start

AWS's managed messaging building blocks (distributed-systems/message-brokers/05-queues_and_topics):

  • SQS (Simple Queue Service) — a queue: each message is processed by one consumer.
  • SNS (Simple Notification Service) — a topic: each message is pushed to every subscriber.
  • Together (SNS → SQS fan-out) they give "every service gets every event, instances of one service share the work".

1SQS Basics

bash
aws sqs create-queue --queue-name orders-email \
  --attributes VisibilityTimeout=60,MessageRetentionPeriod=345600,ReceiveMessageWaitTimeSeconds=20
aws sqs send-message --queue-url $Q --message-body '{"orderId":"o-17"}'
aws sqs receive-message --queue-url $Q --max-number-of-messages 10 --wait-time-seconds 20
aws sqs delete-message --queue-url $Q --receipt-handle "$HANDLE"

The consumer lifecycle:

text
ReceiveMessage → message becomes INVISIBLE for VisibilityTimeout seconds
  ├─ process OK → DeleteMessage (this is the "ack")
  └─ crash / no delete → after the timeout it becomes visible again → redelivered
SettingMeaningGuidance
visibility timeouthow long a received message stays hidden> p99 processing time (≈ 6× for Lambda); extend with ChangeMessageVisibility for long jobs
long polling (WaitTimeSeconds up to 20)wait for messages instead of returning emptyalways on — fewer empty receives, lower cost
retention1 min – 14 days (default 4 days)longer than any expected consumer outage
delayhide new messages for up to 15 minsimple delayed jobs
max message size256 KBlarger payloads → S3 + pointer
redrive policyafter maxReceiveCount receives → DLQalways configure (distributed-systems/message-brokers/10-dead_letter_queues)

2Standard vs FIFO

StandardFIFO (.fifo suffix)
throughputnearly unlimited300 msg/s per API action (3,000 with batching; much higher in high-throughput mode, per message group)
deliveryat least once (occasional duplicates)exactly-once processing within a 5-minute dedup window
orderingbest effortstrict per MessageGroupId
dedupnoneMessageDeduplicationId or content-based

Use FIFO when per-entity order matters (MessageGroupId = orderId); otherwise Standard + idempotent consumers.

3SNS Basics

bash
aws sns create-topic --name order-events
aws sns subscribe --topic-arn $T --protocol sqs --notification-endpoint $EMAIL_QUEUE_ARN \
  --attributes '{"RawMessageDelivery":"true","FilterPolicy":"{\"type\":[\"OrderPlaced\"]}"}'
aws sns publish --topic-arn $T --message '{"orderId":"o-17"}' \
  --message-attributes '{"type":{"DataType":"String","StringValue":"OrderPlaced"}}'

Subscribers: SQS, Lambda, HTTP(S) endpoints, email, SMS, mobile push, Kinesis Firehose. Filter policies let a subscriber receive only the messages it cares about (on attributes or the body). SNS retries failed deliveries with backoff and can send undeliverable messages to a DLQ (per subscription).

4Fan-Out Pattern

text
orders-service ──publish──► SNS topic "order-events"
                                ├─► SQS "billing"        ─► billing workers (compete)
                                ├─► SQS "email"   (filter: OrderPlaced) ─► email workers
                                └─► SQS "analytics"      ─► Lambda batch → S3

Each subscriber service gets its own queue: independent pace, retries, DLQ and scaling; a slow analytics consumer can't delay billing. The SQS queue's access policy must allow the SNS topic to sqs:SendMessage (condition on aws:SourceArn).

5Consumers: Lambda vs Workers

  • Lambda event source mapping polls SQS for you, invokes with batches (up to 10, or up to 10,000 with a batching window), scales concurrency with queue depth, deletes messages on success. Use partial batch responses (ReportBatchItemFailures) so one bad message doesn't fail the whole batch.
  • ECS/EC2 workers long-poll in a loop; autoscale on ApproximateNumberOfMessagesVisible / age of oldest message (11-scalability_and_monitoring).
Under the HoodWhy SQS Is At-Least-Once▾

A standard queue stores each message redundantly across multiple servers and AZs. Receives are served by sampling a subset of servers (which is also why a short-polling receive can return empty even though messages exist — long polling queries all servers). Visibility is tracked per copy; in rare races (e.g. a server that was unavailable during a receive or delete comes back), a copy that was already deleted elsewhere can be delivered again — hence occasional duplicates and only best-effort ordering. FIFO queues trade throughput for a stronger design: messages of a group are ordered and locked to one consumer at a time (the next message in the group isn't released until the in-flight one is deleted or times out), and a deduplication store rejects repeated IDs within 5 minutes.

A service publishes to an SNS topic which fans out to one SQS queue per subscriber, with filter policies; each queue has its own consumers, visibility timeout, and redrive to a dead-letter queue after maxReceiveCount
A service publishes to an SNS topic which fans out to one SQS queue per subscriber, with filter policies; each queue has its own consumers, visibility timeout, and redrive to a dead-letter queue after maxReceiveCount

⚠️ Common Pitfalls

  1. Visibility timeout shorter than processing — messages processed twice (or forever).
  2. Short polling — high cost, empty receives.
  3. No DLQ — poison messages loop until retention expires.
  4. Non-idempotent consumers on Standard queues.
  5. One queue shared by different services instead of SNS → per-service queues.
  6. Forgetting the SQS access policy for SNS — publishes succeed, nothing arrives.
  7. Huge payloads — use S3 + pointer (extended client library).

📋 Quick Reference

NeedUse
work queueSQS Standard + idempotent workers
ordered per entitySQS FIFO, MessageGroupId = entity id
fan-out to servicesSNS → one SQS per service (+ filter policies)
poison messagesredrive policy → DLQ + alarm
serverless consumersLambda event source mapping + partial batch failures
scaling signalApproximateAgeOfOldestMessage, queue depth

🧠 Key takeaways

  • SQS: consumers poll (use long polling); a received message is hidden for the visibility timeout until deleted.
  • Delivery is at-least-once (Standard) with best-effort order; FIFO gives ordering per group + dedup (lower throughput).
  • SNS pushes to subscribers; SNS → SQS fan-out gives each service its own durable queue (with filter policies).
  • Configure DLQs (maxReceiveCount) and set the visibility timeout > processing time (6× the Lambda timeout for event source mappings).

🎤 Interview Q&A

Questions interviewers ask about this topic. Answer out loud first, then open a card to compare.

Q1SQS vs SNS?core▾

SQS is a queue: messages are pulled and processed by one consumer, with retries and DLQs. SNS is pub/sub: a message published to a topic is pushed to all subscribers (SQS queues, Lambda, HTTP, email, SMS). Combine them for fan-out: SNS → multiple SQS queues.

Follow-ups interviewers ask
  • Why fan out to queues instead of Lambda directly? Buffering, retries and independent processing rates.
Q2Standard vs FIFO queues?core▾

Standard: nearly unlimited throughput, at-least-once delivery, best-effort ordering. FIFO: exactly-once processing within a deduplication window and strict ordering per message group ID, with lower throughput limits.

Follow-ups interviewers ask
  • How do you parallelize FIFO? Use many message group IDs (e.g. per customer).
Q3How does the visibility timeout work?core▾

When a consumer receives a message, it becomes invisible for the visibility timeout; if not deleted before it expires, it reappears for another consumer. Set it longer than processing time, and extend it for long tasks.

Follow-ups interviewers ask
  • What sends a message to the DLQ? Exceeding maxReceiveCount in the redrive policy.
Q4How do you reduce SQS cost and latency?senior▾

Long polling (WaitTimeSeconds up to 20) to avoid empty receives, batch send/receive/delete up to 10 messages, and right-size consumers.

Follow-ups interviewers ask
  • Max message size? 256 KB; store larger payloads in S3 and send a reference.
Q5How do you filter which messages subscribers receive in SNS?core▾

Subscription filter policies on message attributes (or body), so each subscriber receives only relevant events without separate topics.

Follow-ups interviewers ask
  • Alternative for complex routing? EventBridge rules.

🛠️ Practice exercises

Each exercise is a file in this topic folder. Code exercises are self-checking: run them and make the checks pass.

✅ Check yourself

Answer the questions — feedback is instant.

1. What happens to an SQS message a worker receives but never deletes?
At-least-once.
2. Strict ordering per customer is required. Use…
Ordering per message group.
3. Each of 3 services must get every order event and process at its own pace. Pattern?
Fan-out.
4. Why enable long polling?
WaitTimeSeconds up to 20.