Home Resume
Homeβ€Ί Blogβ€Ί AWS Architecture Series #11 β€” SQS vs SNS vs EventBridge: The Decision Tree Enterprises Get Wrong…
AWS AWS Architecture Series

AWS Architecture Series #11 β€” SQS vs SNS vs EventBridge: The Decision Tree Enterprises Get Wrong

SQS is a buffer, SNS is a broadcast, EventBridge is a router. Choosing by what the consumer needs rather than what the message is β€” with the quotas that decide it in production.

Business Challenge

A retail platform runs 40 microservices across four AWS accounts. Two years ago the team made a reasonable-sounding decision: standardise on one messaging service so nobody has to argue about it again. They chose EventBridge, put a single custom bus in the shared services account, and routed everything through it β€” order events, inventory updates, email triggers, cache invalidations, audit records.

It worked until Black Friday. Three things broke in the same hour, and each one was the same mistake wearing a different mask.

1The router was being used as a queue

The inventory reconciliation service could handle roughly 200 events per second. Peak produced 3,000. EventBridge did exactly what a router does β€” it delivered them as fast as it matched them. There was no buffer, so the service shed load, and the retry policy expired before the backlog cleared. Events were lost, and the inventory counts were wrong for two days.

Fix

A consumer that can fall behind needs a queue in front of it. That is SQS's entire job.

2A rule hit a ceiling nobody knew existed

The order.placed rule had accumulated five targets over two years. When a sixth team asked to be added, the request failed. Targets per rule is capped at five, and unlike most EventBridge quotas it is not adjustable. The workaround shipped under time pressure β€” duplicating the rule with a slightly different name β€” doubled the invocation count against a quota they were already close to.

Fix

Fan-out beyond a handful of consumers is SNS's job, or an SNS topic as one EventBridge target.

3The Region mattered and nobody had checked

The platform runs in eu-west-2. The team had load-tested in eu-west-1, where PutEvents allows 10,000 requests per second. In eu-west-2 the default is 1,200. The architecture diagram was identical in both Regions; the capacity was not.

Fix

Treat EventBridge throughput as a per-Region number, and check it in the Region you actually deploy to.

None of these are EventBridge failures. EventBridge did what it is built to do. The failure was upstream of the code: the team chose a service by asking "what should we standardise on?" when the question that decides it is "what does the consumer need?"

Architecture

These three services get compared as if they are alternatives. They are not. They do three different jobs, and the job is visible in what happens to a single message.

Diagram: SQS shown as a buffer where one message reaches exactly one consumer, SNS as a broadcast where one message reaches every subscriber, and EventBridge as a router where rules decide which targets receive the event. Below, the question that selects between them and three production constraints: SQS FIFO throughput per partition, EventBridge regional quota variation, and the pattern of composing them.
Three jobs, not three options. The shape of the delivery β€” one consumer, every consumer, or selected targets β€” is what distinguishes them.

SQS is a buffer

A message goes in, one consumer takes it out, and the queue holds it in between. That gap is the point: it absorbs the difference between how fast work arrives and how fast it can be done. Consumers compete for messages, so scaling out means adding consumers. If they all stop, messages wait β€” up to 14 days, four by default.

Standard queues give at-least-once delivery and near-unlimited throughput. FIFO queues give ordering and exactly-once processing, at a cost covered below. Both support dead-letter queues, which is where a message goes after failing repeatedly rather than being lost or retried forever.

SNS is a broadcast

A message goes to a topic and every subscriber gets its own copy β€” SQS queues, Lambda functions, HTTPS endpoints, email, SMS, Firehose. Subscribers do not compete; they each receive everything, unless a filter policy narrows it. Filter policies match on message attributes or, if you set the policy scope accordingly, on the JSON message body.

The critical property: SNS does not store anything. It delivers, retries per the delivery policy for that endpoint type, and then gives up. A subscriber that is down misses messages. This is why the canonical production pattern is not "SNS to Lambda" but "SNS to SQS to Lambda" β€” the queue is what makes the delivery durable.

EventBridge is a router

Events arrive on a bus. Rules match them against patterns β€” on the event body, not just metadata β€” and matching events go to that rule's targets. Producers do not know who consumes their events, and consumers subscribe by declaring what they care about. That decoupling is why EventBridge suits many-producer, many-team estates where SNS's topic-per-message-type sprawls.

It also ingests from 90-plus AWS services directly, supports archive and replay, and offers Pipes for point-to-point integration with enrichment between a single source and a single target. What it does not offer is a buffer with backpressure.

Why This Architecture Holds Up

The question is about the consumer, not the message

Nearly every wrong choice here comes from classifying the message β€” "this is an event, so EventBridge" β€” rather than asking what the receiving end needs. Three questions settle it in almost every case:

If the answer is yes Use Because
One worker should do this job, and work can pile up SQS Competing consumers, backpressure, retry and DLQ semantics
Several independent systems all need to know SNS Fan-out to many endpoint types, with per-subscription filtering
Who receives it depends on what is inside the event EventBridge Content-based routing, cross-account buses, AWS-native sources, replay

They are not mutually exclusive, and the mature answer is usually a composition: EventBridge routes by content, an SNS topic fans one route out to many teams, and each team owns an SQS queue that absorbs its own load. Every consumer that can fall behind gets a queue. That single rule would have prevented all three of the failures above.

The pattern worth memorising

Distribution and buffering are separate concerns. EventBridge and SNS distribute. SQS buffers. Reaching for one to do the other's job is the mistake that shows up under load, never in testing.

FIFO ordering costs more than it looks

"We need ordering" is usually said before anyone checks the price. An SQS FIFO queue is stored in partitions, and each partition supports 3,000 messages per second with batching, or 300 without. Which partition a message lands in is decided by hashing its message group ID.

That last detail is where designs come apart. Ordering is only guaranteed within a message group, and parallelism is bounded by how many distinct groups you have. Use the customer ID and you get wide distribution. Use a single constant because "we need global ordering" and the entire queue collapses onto one partition and a 300/s ceiling. AWS's own guidance is to choose group IDs with a large number of distinct values.

Ask what actually needs ordering

Global ordering across an entire stream is rarely the real requirement. Ordering per customer, per account, or per aggregate almost always is β€” and that maps directly onto a message group ID that partitions well.

Replay is a capability, not a nice-to-have

EventBridge archive and replay is the one capability with no equivalent in the other two. When a downstream consumer ships a bug that mangles a day of events, replay lets you re-drive them after the fix. With SNS the messages are gone. With SQS they are gone once deleted. For audit-sensitive or financially material flows, that alone can decide the choice.

Key Architecture Decisions

Decision Choice Reasoning
Default in front of consumers An SQS queue, always Any consumer that can slow down needs somewhere for work to wait. Cheap insurance against the failure that only appears at peak.
Fan-out beyond a few targets SNS, or SNS as an EventBridge target EventBridge caps targets per rule at five and will not raise it. SNS fan-out has no comparable ceiling.
Routing on event content EventBridge rules SNS filter policies work on attributes or a JSON body, but rule-based routing across many producers and teams is what the bus is for.
Ordering FIFO only where ordering is a business requirement Throughput drops to per-partition limits and parallelism is bounded by distinct message group IDs. Do not buy it by default.
Recoverability EventBridge archive where events are material Replay after a downstream bug is impossible with SNS and gone-once-deleted with SQS.
Capacity planning Check quotas per Region, not per service EventBridge PutEvents ranges from 10,000/s to 400/s depending on Region. The diagram does not change; the headroom does.

What each one is bad at

SQS cannot fan out

One message, one consumer. Needing five systems to react means five queues and something upstream to populate them β€” which is SNS or EventBridge.

SNS cannot wait

No storage. A subscriber that is down misses the message once retries are exhausted. Subscribe a queue if the delivery has to survive an outage.

EventBridge cannot absorb

No backpressure. It delivers as fast as it matches. A slow target either keeps up, is throttled, or loses events after retries expire.

None of them is a stream

Multiple consumers reading the same ordered log at their own offsets, replayed at will, is Kinesis or MSK. Bending these three into that shape produces the worst of both.

A test that settles most arguments

Ask what should happen if the consumer is down for an hour. "Work waits" means SQS. "It missed it, that's fine" means SNS. "Route it based on what it is, and I want to replay it later" means EventBridge. The answer is a business decision, not a technical preference.

Closing Thought

The instinct to standardise on one messaging service is a good instinct applied to the wrong layer. Standardising on conventions β€” event naming, schema versioning, where dead letters go, who owns replay β€” pays off permanently. Standardising on the transport forces one tool to cover three jobs, and the seams tear under load rather than in review.

What makes this decision unusually cheap to get right is that the three services compose cleanly. An EventBridge rule can target an SNS topic. An SNS topic can fan out to SQS queues. A queue can front a Lambda. You are not choosing one and living with it; you are assembling the routing, the fan-out and the buffering from the pieces that do each job properly.

The team in this scenario did not need to migrate off EventBridge. They needed queues in front of four consumers, an SNS topic behind one over-subscribed rule, and to read the quota page for the Region they actually run in. Three weeks of work, and none of it was a rewrite.

Next in this series

Observability β€” CloudWatch, OpenTelemetry, and what centralised telemetry across a multi-account estate actually costs. Where the managed path is the right one, where it stops being affordable, and how teams end up paying twice for the same signal.

Official AWS Reference

  • What is Amazon Simple Queue Service? — includes AWS's own comparison of SQS, SNS and Amazon MQ, the message lifecycle, retention limits, and the FIFO throughput and partitioning rules referenced above.

Comments

How was your experience?
Your feedback helps improve this site.
PoorExcellent