Choice 03. By Nicolas Dao

SQS, EventBridge or SNS?

Something happens in my app and other code must act on it. Do I put it in a queue, on an event bus, or on a topic?

SQS for work between your own services: it buffers, retries and lets Lambda take messages in batches. EventBridge for routing events by their content and for anything on a clock. SNS for simple fan-out, alerts and mobile push. Often all of them: EventBridge or SNS copies the event, and one SQS queue per consumer sits in front of each Lambda.

When to pick which

Pick SQS when

  • One producer hands work to one consumer, and the work must survive spikes and failures.
  • Lambda should take messages in batches: ingestion from devices or webhooks into Postgres.
  • A fragile downstream (a small Postgres, a rate-limited API) must be protected from bursts.
  • Urgent messages need their own path: one queue per priority, so an alarm never waits behind a backlog.
  • Order or exactly-once processing matters: a FIFO queue.

Pick EventBridge when

  • Reacting to AWS itself: an object lands in S3, an ECS task stops with an error, a security finding appears.
  • Events are routed to different targets by their content.
  • Anything on a clock: nightly jobs, monthly invoices, one-off timers per record, in the client's time zone (Scheduler).
  • Events cross a boundary: between AWS accounts, or between teams that shouldn't know each other's code.

Pick SNS when

  • A handful of subscribers all want the same message.
  • Operational alerts: CloudWatch alarms to email or an HTTPS endpoint.
  • Mobile push to Apple and Google devices from your backend.
  • Ordered fan-out: a FIFO topic into FIFO queues.

Both, when

  • Fan-out into queues: SNS or an EventBridge rule copies the event, one SQS queue per consumer takes it, and each Lambda reads its own queue in batches, with its own retries and dead-letter queue.
  • EventBridge and SNS sit side by side too: EventBridge for business events routed by content and for schedules, SNS for alerts, push and simple broadcasts. I use both.
  • Inside one app, SQS alone usually does it: a queue between your own services is easier to reason about and debug than events on a bus.

Questions that change the answer

  • How many consumers does each message have? One is a queue; several is a topic or a rule, with a queue per consumer behind it.

  • Is it work or news? Work needs back-pressure, retries and a dead-letter queue, which only SQS holds; news only needs to reach whoever cares.

  • Does the target depend on what's in the event? Routing by content is EventBridge's job; SNS filters on attributes for free, payload filters cost per GB.

  • How many messages a second at peak? In Sydney, EventBridge allows 1,200 PutEvents calls a second and SNS 1,500 publishes by default; telemetry belongs in SQS or Kinesis.

  • Does it happen at a time rather than because of something? That's EventBridge Scheduler.

The short version

SQS EventBridge SNS
My verdict My default My default Use when it fits
Job Work from a producer to one consumer Route events by content; schedules Copy one message to every subscriber
Keeps messages for you Yes, until a consumer takes them No: retries delivery, then drops it without a DLQ No: retries, then discards without a DLQ
Retry window on failure Your settings (visibility timeout, maxReceiveCount) 24 hours, 185 attempts by default Retries, then discards
Into Lambda In batches Per event One invocation per message
Back-pressure Yes: cap the consumer's concurrency No No
Ordering FIFO queues None on the classic bus FIFO topic into FIFO queues
Filtering None: one consumer Rules on the event's content Attributes free, payload $0.11/GB scanned
Schedules and timers Delays up to 15 minutes Scheduler: time zones, 10 million schedules per Region No
Default rate in Sydney — 1,200 PutEvents calls a second 1,500 publishes a second, per account
Price in Sydney $0.40 per million requests, up to 10 messages each $1 per million custom events; Scheduler $1.20 per million after 14 million free $0.50 per million publishes after 1 million free; deliveries to SQS and Lambda free
Delivery At least once At least once At least once

Price doesn't decide this one: all three are cheap. Shape decides it. SQS is a buffer with one reader. EventBridge is a router and a clock. SNS is a broadcaster that keeps nothing.

Three neighbours come up in the same conversation and do other jobs. Kinesis is for ordered, very high-volume streams that several consumers replay, and it gets expensive fast (about $36 a month per on-demand stream, even idle). Firehose lands records in S3 as files, with no consumer to write, but no per-message retries or DLQ either. Cloudflare Queues is a Skip inside AWS: a Worker that must feed AWS sends to SQS directly.

SQS for work, with back-pressure and retries

SQS in front of Lambda is the most boring, reliable pattern in my stack. A queue holds the work until the consumer is ready, so a spike becomes a backlog instead of an outage. Lambda takes messages in batches, which keeps invocations, database connections and the bill small: 50 million messages cost about $6 batched, $60 unbatched. Cap the consumer's maximum concurrency and Postgres never sees more than a handful of connections, whatever the burst.

Its only pain is configuration. Three settings cover nearly every dead-letter surprise:

  • Visibility timeout at least six times the function timeout, or messages reappear and run twice while still being processed.
  • ReportBatchItemFailures, returning only the failed message IDs, or one bad message retries the whole batch.
  • maxReceiveCount set deliberately (for example 3–5), with an alarm on the dead-letter queue's depth.

Urgent messages get their own queue: batch size 1, no batching window, their own function, and an alarm on ApproximateAgeOfOldestMessage. A queue tuned for throughput holds an alarm behind the batching window and the backlog. A fire alarm at 2:14 am is built on that split. How the retries themselves work, and when they stop being enough, is in SQS retries or Durable Functions?.

EventBridge for routing and time

I use EventBridge for two jobs. The first is reacting to AWS itself: AWS publishes its events to the default bus, and a rule routes them by content to a Lambda, a queue or an alert. The second is time: Scheduler runs nightly jobs and creates one-off timers from code ("remind this user in 24 hours", "expire this quote on Friday"), in the client's own time zone. The old scheduled rules on the bus run in UTC only, so a 9 am Sydney job drifts by an hour twice a year.

Where I'm careful is using it as the backbone between my own services. Event-driven designs look great on a diagram and are hard to debug once five things happen asynchronously. Inside one app, a function call or an SQS queue is easier to reason about, for humans and for AI agents. EventBridge earns its place at the boundaries: between AWS services, between accounts, between teams.

Design for two things from day one. Delivery is at least once and the classic bus has no ordering, so every target must ignore what it has already processed. And a delivery that keeps failing is retried for 24 hours, then dropped silently: I put an SQS dead-letter queue on every rule target and every schedule. The new Custom Event Bus (September 2026) adds retention, replay, FIFO per event group and deduplication, but it has no Terraform or Pulumi resource yet, so I still provision the classic bus.

SNS for simple fan-out, and when to run them together

SNS is a broadcaster. One publish, and every subscriber gets a copy: a few queues, a Lambda, a webhook, the on-call's email, a phone. It keeps nothing. Use it for alerts, mobile push and a handful of subscribers who want the same message. Not for customer email (plain text, 10 messages a second per subscription), and not to wake someone up: it can't call, and can't tell you a person saw the message.

Its trap is the ingestion path. SNS calls Lambda once per message, so a burst becomes thousands of tiny invocations with nothing holding them back, and in Sydney an account publishes only 1,500 messages a second by default, across all its topics. When a subscribed function keeps failing, Lambda retries it twice, then drops the event. In IoT ingestion into Postgres, dropping SNS for SQS is a large part of what takes the bill from about $1,100 to $215–410 a month.

The pattern I trust runs them together: SNS or an EventBridge rule → one SQS queue per consumer → Lambda in batches. The topic or the rule only copies, and copies into SQS are free on SNS. Each consumer gets its own buffer, its own retry settings and its own DLQ, so a failing consumer never blocks the others, and adding one means adding a queue, not touching the publisher. Pick SNS for the copy when every consumer wants every message; pick an EventBridge rule when each consumer wants only some of them, chosen by content. Devices are the same shape: an IoT Core rule writes straight to SQS, so Lambda takes readings in batches.

Sources, checked on 25 October 2026: Using Lambda with SQS, SQS pricing, EventBridge Scheduler, Scheduler schedule types, EventBridge retries, EventBridge pricing, the new Custom Event Bus, SNS pricing, SNS quotas, SNS delivery retries, Kinesis Data Streams pricing.

More choices

  1. 01 Lambda, Web Functions or Workers? Where should this piece of logic run?
  2. 02 Lambda, Fargate or EC2? My Lambda is busy all day, or its reserved concurrency keeps going up. When is it time to move to a container, and where is the line?
  3. 04 SQS retries or Durable Functions? A job calls something flaky (a third-party API, an LLM, a slow Postgres). How do I retry it reliably, and when do I reach for Lambda durable functions instead of tuning SQS?
  4. 05 pgvector or S3 Vectors? Where should my embeddings live?
  5. 06 Pulumi or Terraform? We're putting our infrastructure in code. Pulumi or Terraform, and what if we already run one of them?
  6. 07 Cloudflare or S3 and CloudFront for a website? Where should a website, SPA or PWA live, Cloudflare static hosting or S3 behind CloudFront, and where do its heavy files go?
  7. 08 CloudWatch and Firehose, side by side How do I keep chatty logs without a CloudWatch-sized bill?
  8. 09 Athena or DuckDB? How should I query my data lake, and what changed when AWS bought DuckDB's company?
  9. 10 Neon or Aurora? I need Postgres for an app on AWS. When is Neon the right call, and when does it have to be Aurora?
  10. 11 Better Auth or Cognito? Which sign-in should my app use, and what do I actually get for free?
  11. 12 Why I ended up on AWS Which cloud should my company run on, and is AWS just the one you know?
  12. 13 Better Auth, run yourself or managed by Neon? My app is on Neon. Should I run Better Auth myself, or switch on Neon Auth, which is Better Auth managed by Neon?
  13. 14 Stripe or PayPal Should we take payments with Stripe or PayPal, and when is PayPal worth the pain?
  14. 15 Tailscale or Cloudflare Tunnel? I need to reach a private box or VPC, or put a service from it online. Is that Tailscale or Cloudflare Tunnel?
  15. 16 Resend or SES? Our app sends email, and maybe a newsletter. Resend, or Amazon SES in our own AWS account?
  16. 17 WhatsApp or Telegram Our bot should reach users in a messaging app. WhatsApp or Telegram, and why did yours get blocked?
  17. 18 Which model, at what price Claude, GPT or an open model? Which is the cheapest model that's good enough, tier by tier?
  18. 19 Function URL or API Gateway? My Lambda needs an HTTPS endpoint. When is a function URL enough, and when do I start on API Gateway from day one?

Want this stack in your AWS account?

Cloudless Labs is a Sydney consultancy. We migrate on-premises systems to AWS, build serverless apps on this stack, and coach teams to ship with Claude Code and Codex.

Contact Us

For general inquiries, please contact us at:

For e-learning capabilities, please contact: