Series: Event-Driven Architecture on AWS · Part 3 of 3
- Queue Everything: How SQS-Based Architecture Improved Our API Response Times
- EventBridge Pipes and Scheduler: Deleting the Glue Lambdas
- EventBridge vs SNS: When to Use Which (and When to Use Both)
Contents
Why This Keeps Coming Up
In an earlier post I explained why we queue almost everything with SQS. The natural next question is: when one thing happens (an order is placed, a subscription is paused) and several services care, how do you fan that event out? On AWS there are two obvious answers: Amazon SNS and Amazon EventBridge. Both are serverless, both do publish/subscribe, and both pair well with SQS. They're built for different jobs.
SNS in One Paragraph
SNS is a topic-based pub/sub service. Publishers send a message to a topic; every subscriber to that topic gets a copy. Subscribers can be SQS queues, Lambda functions, HTTP endpoints, email, SMS or mobile push. It's very high throughput, very low latency, and simple. Subscription filter policies let a subscriber receive only messages matching attributes (or, more recently, the message body). FIFO topics give you ordering and de-duplication when paired with SQS FIFO queues.
EventBridge in One Paragraph
EventBridge is an event bus with a rules engine. Publishers put events onto a bus; rules match events by content (source, detail-type, any field in the payload) and route them to targets. Beyond basic routing, it offers: a schema registry, archive and replay, input transformation, cross-account and cross-region buses, scheduled rules and EventBridge Scheduler, Pipes (point-to-point source → filter → enrich → target), API destinations for calling third-party HTTP APIs, and native events from AWS services and SaaS partners.
The Key Differences
| SNS | EventBridge | |
|---|---|---|
| Mental model | Topic → subscribers | Bus → rules → targets |
| Filtering | Filter policies on attributes/body | Rich content-based pattern matching on any field |
| Targets | SQS, Lambda, HTTP(S), email, SMS, mobile push, Firehose | 20+ AWS services, API destinations, other buses |
| Fan-out per event | Very large number of subscriptions per topic | Limited number of targets per rule (use multiple rules) |
| Throughput and latency | Very high, typically lower latency | High, with slightly higher latency |
| Ordering | FIFO topics available | No ordering guarantees |
| Replay | FIFO topics only (message archiving and replay); none for standard topics | Built-in archive and replay |
| Schemas | None | Schema registry and discovery |
| AWS service events | Some services publish to SNS | Most AWS services emit events to the default bus |
| SaaS integrations | No | Partner event sources (e.g. Stripe, Zendesk, Shopify via partners) |
| Transformation | No | Input transformers, Pipes enrichment |
| Cost profile | Very cheap per million | Cheap per million, more than SNS for custom events |
Check the current AWS quotas for your region before designing around specific limits, as they change over time.
When I Reach for SNS
- Simple, high-volume fan-out. One producer, a handful of consumers, lots of messages, latency-sensitive. SNS → multiple SQS queues is the classic, cheap and very reliable pattern.
- Human notifications. SMS, email and mobile push are built in. CloudWatch alarms → SNS → PagerDuty/Slack is still the simplest alerting path.
- Ordered fan-out. When you need strict ordering per entity (e.g. ledger events per account), SNS FIFO → SQS FIFO is the tool.
- Very large numbers of subscribers. Per-tenant or per-device subscriptions are what SNS is built for.
When I Reach for EventBridge
- Domain events between teams or services.
OrderPlaced,SubscriptionPaused,PaymentFailed. Consumers write their own rules on the payload without the producer knowing they exist. That decoupling is the whole point. - Content-based routing. "Send
PaymentFailedevents wheredetail.amount > 100anddetail.marketis 'UK' or 'IE' to the collections service." Filter policies can do some of this; EventBridge rules do it naturally. - Reacting to AWS itself. EC2 state changes, ECS task failures, CloudWatch alarm state changes, GuardDuty findings, and S3 object events (once EventBridge notifications are enabled on the bucket). They arrive on the default bus.
- SaaS events. Receiving events from partners without writing a webhook receiver.
- Replay. When you ship a buggy consumer and need to reprocess last Tuesday's events, archive and replay is invaluable.
- Scheduling. EventBridge Scheduler has largely replaced the "cron Lambda" for us.
- Calling external APIs. API destinations with built-in auth and rate limiting, so you don't write yet another Lambda that just forwards JSON.
A Rule for Rules
{
"source": ["com.company.payments"],
"detail-type": ["PaymentFailed"],
"detail": {
"market": ["UK", "IE"],
"amount": [{ "numeric": [">", 100] }]
}
}Routing that pattern to an SQS queue owned by the collections team means the payments team never has to know about collections, and collections can change its interest without a deploy from payments.
The Pattern I Use Most: EventBridge for Routing, SQS for Consumption
Whichever you choose, don't point a bus or topic directly at a Lambda for anything that matters. Put an SQS queue in between:
Producer → EventBridge bus → rule → SQS queue (per consumer) → Lambda worker
↳ DLQ with alarmThe queue gives each consumer its own buffer, retry policy, concurrency control and dead-letter queue. When a consumer is broken, its events wait rather than disappearing. And you can pause one consumer without affecting the others.
Using Both Together
They aren't mutually exclusive. A common and sensible architecture:
- EventBridge as the domain event backbone between services and teams.
- SNS at the edges: alarms to on-call, customer SMS and push notifications, or a very high-volume internal stream where EventBridge's routing features aren't needed.
Startup vs Scaleup vs Enterprise
Startup: Honestly, you may need neither yet. SQS alone handles most async work. When you first need fan-out, pick EventBridge for domain events because the rule-based decoupling will save you later, and it's cheap at startup volumes.
Scaleup: Introduce a naming convention for sources and detail-types, publish schemas, and enable archives on the main bus. This is when event contracts between teams start to matter.
Enterprise: Cross-account buses per domain, a central event catalogue, schema governance, and SNS for the very high-volume or notification use cases where EventBridge's features aren't needed.
The Takeaway
If you're notifying people, devices or a known set of queues at very high volume, use SNS. If you're integrating (letting services and teams react to business events without coupling, with routing, replay and AWS/SaaS events in the mix), use EventBridge. And in both cases, land messages in an SQS queue before you process them.
