Decoupling & Events¶
Pick the wrong one of these four and you find out the hard way — a queue that deletes-on-read when you needed to replay history, or a fan-out that silently assumes every subscriber handles failure the same way. The four services below aren't interchangeable "eventing" tools; each commits to a different delivery guarantee, and the skill this page teaches is reading a scenario for the guarantee it actually needs before reaching for the name you happen to recognize.
Scope: the AWS module page named the decoupling primitives at a glance — SQS decouples producer from consumer, SNS fans an event out to many subscribers, EventBridge is the general event bus and scheduler. This page goes one layer deeper: what each one is actually for, adds the fourth primitive the overview didn't cover (Kinesis, for streams), and gives you a way to pick the right one from a two-line scenario instead of by name recognition.
TL;DR — in 30 seconds:
- Three structurally different shapes, not interchangeable tools: a queue (SQS) delivers one message to one consumer; fan-out (SNS) delivers one message to every subscriber; a stream (Kinesis) is an ordered, replayable log multiple readers can rewind.
- EventBridge generalizes fan-out with content-based routing (rules match on the event, route to different targets) and adds a built-in scheduler — pick it when different events need to go different places, not just "everyone gets everything."
- SQS FIFO queues trade throughput for guaranteed order and exactly-once processing within a message group — reach for them only when out-of-order or duplicate processing would actually break correctness.
1. Three shapes, one underlying question¶
Every one of these services exists to let a producer stop caring about its consumers — but they decouple in three structurally different shapes, and picking the wrong shape is the usual mistake:
- Queue — one message, delivered to one consumer, held until it's processed. The shape for work that must happen exactly once, at whatever pace the consumer can handle.
- Fan-out — one message, delivered to every subscriber. The shape for "many independent parts of the system all need to know this happened."
- Stream — an ordered, replayable log of events that consumers read at their own pace, and can re-read. The shape for "I need the history, not just the latest event."
flowchart LR
subgraph Queue["Queue — SQS"]
P1["Producer"] --> Q["Queue"] --> C1["One consumer"]
end
subgraph FanOut["Fan-out — SNS"]
P2["Producer"] --> T["Topic"]
T --> S1["Subscriber A"]
T --> S2["Subscriber B"]
T --> S3["Subscriber C"]
end
subgraph Stream["Stream — Kinesis"]
P3["Producer"] --> L["Ordered log"]
L --> R1["Reader (now)"]
L --> R2["Reader (replay)"]
end
EventBridge doesn't add a fourth shape so much as it generalizes fan-out: instead of one topic with subscribers, it's a bus with rules that route an event to different targets based on the event's own content — and it adds a scheduler on top.
2. SQS — the queue¶
SQS (Simple Queue Service) holds messages until exactly one consumer picks each one up and deletes it. The point of a queue is buffering: the producer can push faster than the consumer can process, and the queue absorbs the difference instead of the producer blocking or the consumer falling over.
- Standard queues deliver at-least-once and don't guarantee order — the default, and the right choice unless you have a specific reason not to use it.
- FIFO queues guarantee order and exactly-once processing within a message group, at lower throughput — reach for this only when out-of-order or duplicate processing would actually break correctness (e.g. applying account balance updates in sequence).
- Queue depth (how many messages are waiting) is a genuinely good autoscaling signal for the consumer fleet — a growing queue means consumers can't keep up, which is a direct, low-noise "scale out" trigger.
Pick SQS when: one consumer needs to do one unit of work per message, and you want the producer and consumer to scale independently.
3. SNS — fan-out¶
SNS (Simple Notification Service) is a topic: a producer publishes one message once, and SNS delivers a copy to every current subscriber — other queues, Lambda functions, HTTP endpoints, email, or SMS.
The classic pattern is fan-out to SQS: publish once to an SNS topic, and let several SQS queues subscribe to it, one per downstream service. Each service gets its own durable, independently-scaling copy of every event, without the producer knowing any of those services exist.
Pick SNS when: more than one independent consumer needs to react to the same event, and you don't want the producer to know or care who they are.
4. EventBridge — the event bus and scheduler¶
EventBridge generalizes the fan-out idea with content-based routing: instead of "every subscriber gets everything," you write rules that match on the event's own fields and route matching events to different targets (a Lambda function, a Step Functions workflow, another SQS queue, and so on).
Two things make EventBridge distinct from SNS in practice:
| SNS | EventBridge | |
|---|---|---|
| Routing | every subscriber gets every message | rules match on event content; different events go to different targets |
| Sources | your own publishers | your own publishers, plus built-in integrations with most AWS services, and third-party SaaS sources |
| Extra feature | — | a built-in scheduler (cron-like rules) for time-based triggers, no separate service needed |
Pick EventBridge when: different events need to go to different places based on their content, or you want to react to AWS-service or SaaS events without wiring up your own publisher.
5. Kinesis — the stream¶
Kinesis Data Streams is the odd one out: it doesn't just deliver a message and forget it — it keeps an ordered, replayable log of records for a configurable retention window (up to days). Multiple consumers can each read the stream independently, at their own position, and a consumer can rewind and re-process history — something none of the message-oriented services above support.
That makes Kinesis the right tool when the history itself is the point: real-time analytics over a click stream, feeding the same event data to several independent processing pipelines that each need to replay from a different point, or ordered event sourcing where downstream state is rebuilt by replaying the log. (Go deeper: the Kinesis Data Streams retention guide — optional, not required to defend this page.)
Pick Kinesis when: you need ordered replay, multiple independent readers over the same history, or sustained high-throughput streaming ingestion — not just "deliver this event."
6. Choosing per scenario¶
flowchart TD
Q1{"Do readers need to replay<br/>or rewind history?"}
Q1 -->|"yes"| Kinesis["Kinesis"]
Q1 -->|"no"| Q2{"Delivered to one consumer,<br/>or many?"}
Q2 -->|"one"| SQS["SQS"]
Q2 -->|"many"| Q3{"Same message to everyone,<br/>or route by content/schedule/<br/>native AWS integration?"}
Q3 -->|"everyone gets everything"| SNS["SNS"]
Q3 -->|"route per event"| EventBridge["EventBridge"]
| Scenario | Primitive | Why |
|---|---|---|
| Smooth out bursty traffic to a worker fleet | SQS | buffering + queue-depth autoscaling |
| One order-placed event needs to notify billing, shipping, and analytics independently | SNS (fan-out to SQS per consumer) | each consumer gets its own durable copy |
| Route different event types to different Lambda functions | EventBridge | content-based rules, not blanket fan-out |
| Run a job on a schedule with no separate cron infrastructure | EventBridge | built-in scheduler |
| React to a native AWS event (e.g. an S3 upload, an EC2 state change) | EventBridge | built-in AWS service integrations |
| Real-time clickstream feeding several analytics pipelines that each need to replay history | Kinesis | ordered, replayable log; multiple independent readers |
7. How this connects¶
- This extends the AWS module page's decoupling-primitives table (SQS/SNS/EventBridge) with the mechanism behind each choice, adds Kinesis as the fourth (stream) shape the table didn't cover, and gives §6's scenario table as the pick-per-situation reference the module's Pair beat exercises.
- The module's Pair prompt — "give me a workload and make me pick between ALB/NLB/GWLB, and separately between DynamoDB/RDS/Aurora" — is the same style of forced pick this page's §6 table trains for the decoupling primitives.
Common gotchas
- Using SQS when the history itself is what's needed. Fix: SQS deletes a message once a consumer processes it — there's no replay. Reach for Kinesis when multiple independent readers each need to rewind and re-process the same history.
- Defaulting to SNS fan-out when only one consumer should ever act on an event. Fix: fan-out means every subscriber gets a copy — if only one thing should ever process a given message exactly once, that's SQS's shape, not SNS's.
- Reaching for FIFO queues by default. Fix: FIFO trades throughput for guaranteed order and exactly-once-per-message-group — use Standard queues (at-least-once, unordered, higher throughput) unless a concrete correctness reason (e.g. sequential balance updates) needs FIFO's guarantee.
- Building a custom event router instead of using EventBridge's content-based rules. Fix: EventBridge already routes different event types to different targets based on the event's own fields, plus built-in AWS-service and SaaS source integrations and a scheduler — reinventing that on top of SNS/SQS is usually unnecessary.
- Ignoring queue depth as an autoscaling signal. Fix: a growing SQS queue directly means the consumer fleet can't keep up — it's a low-noise, direct "scale out" trigger that's easy to overlook in favor of CPU-based scaling alone.
Check yourself — a real-time clickstream needs to feed three independent analytics pipelines, each replaying from a different point in history. Which primitive, and why not SNS?
Kinesis — SNS fans a message out once to each current subscriber but doesn't retain a replayable log; Kinesis keeps an ordered log for a retention window that multiple independent readers can each rewind and re-process at their own position, which is exactly what "replay from a different point" needs.
Check yourself — one order-placed event needs to notify billing, shipping, and analytics — each independently, each getting its own durable copy. What's the pattern, and which two services combine to build it?
Fan-out to SQS: publish once to an SNS topic, and let a separate SQS queue subscribe per downstream service — each service gets its own durable, independently-scaling copy of every event without the producer needing to know any of them exist.
You can defend this when you can say, for any event-driven scenario, whether it needs a queue, a fan-out, content-based routing, or a replayable stream — and explain what specifically breaks if you used the wrong shape (a stream reader that needed to replay history but got SQS's delete-on-read queue instead, or a producer that had to know all its consumers because it used a queue instead of a topic).