The confusion is understandable
Both SQS and SNS are AWS messaging services. Both let services talk to each other asynchronously. Both are fully managed. If you’re new to the AWS ecosystem, it’s natural to wonder why two services that look so similar exist side by side.
The difference is fundamental: SQS is a queue, SNS is a pub/sub system. They solve different problems, and conflating them leads to designs that are either over-engineered or broken in subtle ways. This post breaks down the distinction and gives you a clear mental model for picking the right tool.
Amazon SQS — the queue
Simple Queue Service (SQS) is a fully managed message queue. A producer puts messages into the queue; a consumer polls the queue and processes them one by one. Once a message is successfully processed, the consumer deletes it. If processing fails, the message becomes visible again after the visibility timeout expires, so another consumer can retry it.
SQS — pull-based, point-to-point queue
Key characteristics
- Pull-based — consumers actively poll the queue for messages. SQS supports long polling (up to 20 seconds) to reduce empty responses and cost.
- At-least-once delivery — messages are guaranteed to be delivered at least once. Duplicate delivery is possible in rare cases; design consumers to be idempotent.
- Visibility timeout — when a consumer picks up a message, it becomes invisible to other consumers for a configurable period. If processing fails, it reappears.
- Dead-letter queues (DLQ) — messages that fail repeatedly move to a DLQ for investigation and manual replay.
- Retention — messages persist in the queue for up to 14 days, even if no consumer is running.
- FIFO queues — for workloads that require strict ordering and exactly-once processing, SQS offers a FIFO variant.
One queue, one logical consumer
You can run multiple worker instances polling the same queue for horizontal scaling, but each message is processed by exactly one of them. SQS is fundamentally a work distribution mechanism, not a broadcast mechanism.
Amazon SNS — the pub/sub system
Simple Notification Service (SNS) is a fully managed pub/sub service. A publisher sends a message to a topic. SNS immediately fans that message out to all subscribers — simultaneously, in parallel. Subscribers can be SQS queues, Lambda functions, HTTP/HTTPS endpoints, email addresses, or SMS.
SNS — push-based, fan-out to multiple subscribers
Key characteristics
- Push-based — SNS pushes messages to subscribers immediately. There is no polling; delivery is near real-time.
- Fan-out — every subscriber receives every message. If you have five subscribers, the message is delivered five times in parallel.
- No persistence — SNS does not store messages. If a delivery attempt fails and the subscriber is unavailable, the message can be retried (with a configurable retry policy), but there is no durable queue behind the topic itself.
- Message filtering — each subscription can attach a filter policy so that only matching messages are delivered. This avoids routing logic in consumers.
- Multiple protocol support — HTTP/HTTPS, SQS, Lambda, email, SMS, and mobile push notifications are all valid subscriber types.
Side-by-side comparison
| Property | SQS | SNS |
|---|---|---|
| Delivery model | Pull (consumers poll) | Push (SNS delivers) |
| Consumers per message | One | All subscribers (fan-out) |
| Message persistence | Up to 14 days | Not persisted; delivery only |
| Delivery guarantee | At-least-once | At-least-once per subscriber |
| Ordering | Standard or FIFO | No ordering guarantee |
| Rate limiting / buffering | Yes — queue absorbs spikes | No — immediate fan-out |
| Message filtering | Not built-in | Per-subscription filter policies |
| Dead-letter queues | Native DLQ support | Supported for SQS/Lambda subscribers |
| Primary use case | Work queue, task offloading | Event broadcast, notifications |
When to use SQS
Use SQS whenever you need to decouple a producer from a consumer and control the rate of processing. The queue acts as a buffer — it absorbs bursts of incoming work and lets your consumer scale independently.
Classic scenarios
- Task offloading — a web API receives a request, writes a job to SQS, and returns immediately. A background worker processes the job at its own pace. The user gets a fast response; the heavy work happens asynchronously.
- Rate limiting downstream services — if an external API you call has a rate limit of 10 requests per second, SQS lets you absorb spikes and drain the queue at a controlled rate. Without a queue, burst traffic would hit the API directly and fail.
- Retry and durability — messages survive consumer restarts, crashes, and deployments. Nothing is lost. Combined with a DLQ, you get visibility into failed messages without custom error stores.
- Ordered processing — financial transactions, audit logs, and state machines where message order matters should use a FIFO queue.
- Competing consumers pattern — scale horizontally by adding more consumer instances. SQS distributes messages across them automatically; no coordination needed.
# Sending a message to SQS (Python, boto3)
import boto3
sqs = boto3.client('sqs', region_name='us-east-1')
response = sqs.send_message(
QueueUrl='https://sqs.us-east-1.amazonaws.com/123456789/order-processing',
MessageBody='{"orderId": "abc-123", "total": 59.99}',
MessageAttributes={
'EventType': {
'DataType': 'String',
'StringValue': 'OrderPlaced'
}
}
)
When to use SNS
Use SNS whenever a single event needs to notify multiple independent systems simultaneously. The publisher does not know or care who the subscribers are. Adding a new subscriber does not require changing the publisher at all.
Classic scenarios
- Event broadcasting — an order is placed, and three systems need to know immediately: payments, inventory, and analytics. SNS delivers to all three in parallel without the publisher coupling to any of them.
- Real-time notifications — mobile push notifications, SMS alerts, or email notifications where low latency matters and persistence is not required.
- Decoupling microservices at the event layer — services publish domain events to topics. Other services subscribe to the topics they care about. Adding a new service means adding a new subscription, not modifying existing code.
- Triggering multiple Lambda functions — SNS is the cleanest way to invoke several Lambdas in response to a single event without chaining them together.
# Publishing to SNS (Python, boto3)
import boto3, json
sns = boto3.client('sns', region_name='us-east-1')
response = sns.publish(
TopicArn='arn:aws:sns:us-east-1:123456789:order-events',
Message=json.dumps({
'orderId': 'abc-123',
'customerId': 'usr-456',
'total': 59.99
}),
Subject='OrderPlaced',
MessageAttributes={
'EventType': {
'DataType': 'String',
'StringValue': 'OrderPlaced'
}
}
)
The SNS + SQS fan-out pattern
In practice, the most powerful setup combines both services. SNS broadcasts the event; each subscriber gets its own SQS queue. This gives you the fan-out of SNS and the durability, retry logic, and rate control of SQS — for every consumer independently.
SNS + SQS fan-out pattern — the best of both worlds
This pattern solves a real problem: if you only use SNS, a slow or temporarily unavailable subscriber will miss messages. If you only use SQS, you need multiple queues and separate producers for each consumer. The combined pattern lets a single publish flow reach multiple isolated, durable queues.
Why this pattern is used everywhere
With SNS + SQS fan-out, each consumer team owns their queue. They can set their own visibility timeout, retry policy, and DLQ. One consumer going down does not affect others. Scaling a single consumer is independent of the rest of the pipeline.
The decision framework
When you’re standing at the whiteboard trying to decide, run through these questions:
- Does exactly one system need to process each event? Use SQS.
- Do multiple independent systems need to react to the same event? Use SNS — or SNS + SQS if those consumers need durability.
- Does the consumer need to process messages at its own pace? Use SQS. The queue buffers the load.
- Is low-latency delivery to multiple endpoints more important than guaranteed processing? Use SNS directly.
- Do you need message ordering? Use SQS FIFO. SNS does not guarantee order.
- Can you tolerate message loss if a subscriber is down? If yes, SNS alone may suffice. If no, add SQS per subscriber.
Gotchas to watch out for
A few non-obvious behaviors that have caught people out in production:
- SQS does not guarantee FIFO by default. Standard queues offer best-effort ordering. If you process messages out of order, you need SQS FIFO and to accept the throughput trade-off (300 msg/s without batching vs. standard’s effectively unlimited).
- SNS retry policy is not a substitute for a DLQ. SNS will retry failed HTTP deliveries with exponential backoff, but the retry window is limited. For any subscriber that might be down for minutes or hours, use an SQS queue instead of HTTP.
- The visibility timeout must exceed your processing time. If your Lambda or worker takes longer than the visibility timeout to process a message, SQS will assume it failed and redeliver it to another consumer — resulting in duplicate processing.
- SNS message size is capped at 256 KB. For large payloads, the pattern is to store the payload in S3 and publish only the S3 object reference through SNS.
- Cross-account SNS → SQS subscriptions require explicit queue policies. The SQS queue must grant
sqs:SendMessageto the SNS topic’s ARN. Missing this is a common source of silent delivery failures.
Closing thoughts
SQS and SNS are complementary, not competing. SQS is a work queue: it buffers, persists, and distributes tasks to a single logical consumer. SNS is a broadcast bus: it fans events out to multiple subscribers simultaneously.
When in doubt, the SNS + SQS fan-out pattern is the safest default for event-driven architectures. It adds modest infrastructure complexity in exchange for durability, independent scaling, and clean decoupling — properties that pay off quickly as a system grows.
If you’re building a new service on AWS and reasoning through messaging patterns, feel free to reach out — happy to think through the design.