13.4
SNS, Fan-Out and Message Filtering
Pub/sub topics, SNS + SQS fan-out, filter policies and FIFO topics.
24 min Reading + animations
Tip: tap or hover any dotted-underlined term to see what it means.
By the end of this lesson you will be able to
- Explain why sending one event to many receivers with direct calls couples the sender to every receiver, and how the publish/subscribe model of Amazon SNS removes that coupling.
- Describe a topic, its publishers and its subscriptions, list the subscriber types (SQS, Lambda, Firehose, HTTP/S, email, SMS, mobile push) and the AWS services that publish to SNS, and know the limits that matter.
- Build the SNS + SQS fan-out pattern correctly: queue access policies, KMS keys, cross-Region and cross-account queues, raw message delivery, and use it for S3 events and for archiving to S3 through Firehose.
- Choose FIFO topics when order and deduplication matter, and predict their throughput, subscriber and replay behaviour.
- Write subscription filter policies (attribute-based and payload-based) and predict exactly which subscriptions receive a message.
- Explain how SNS retries failed deliveries, when a message is lost, and how a subscription dead-letter queue keeps it.
#One event, many receivers
#Direct calls tie the sender to everyone
Lessons 13.1 to 13.3 used a queue: one producer, one kind of consumer, and each message is processed once. Many events are different. When a customer places an order, several parts of the business must hear about it: the warehouse, the notification service, the fraud team, analytics. The same message must reach many receivers.
The direct way is for the order service to call each receiver itself, one after another. The slides draw this as a buying service calling an email notification, a fraud service, a shipping service and an SQS queue. It works on day one and hurts every day after:
- Slow. The order service waits for every call, so each receiver adds its delay to the customer’s checkout.
- Fragile. If one receiver is down or slow, the order service must decide whether to fail the order, retry or give up on that receiver. One weak receiver hurts every order.
- Coupled. A new receiver means changing and redeploying the order service. The sender has to know every receiver’s address, protocol and quirks.
#Publish/subscribe
In the publish/subscribe (pub/sub) model, the sender does not talk to receivers at all. It publishes a message once to a topic, and every receiver that subscribed to the topic gets its own copy. The sender does not know who the receivers are, how many there are, or what they do with the message. Receivers can be added and removed without the sender noticing.
One order, many receivers
A Dhaka food-delivery app must tell the rider service, the fraud check and the customer about every new order. Compare calling each one directly with publishing once to an SNS topic.
Scenario
No topic: the order service knows every receiver and calls them one by one.
Without a topic, the order service has to call every receiver itself. First the rider service.
#Amazon SNS: topics, publishers and subscribers
Amazon Simple Notification Service (SNS) is AWS’s fully managed, push-based pub/sub messaging service. You do not run servers or brokers; you create topics and subscriptions, and SNS scales the delivery.
#The three parts
| Part | What it is | Example |
|---|---|---|
| Topic | A named, logical access point (a channel). Publishers send to it; it has an ARN | arn:aws:sns:ap-southeast-1:111122223333:order-placed-example |
| Publisher | Anything that sends a message to the topic: your application through the SDK or CLI, or an AWS service | the order service, an S3 bucket, a CloudWatch alarm |
| Subscription | One endpoint registered on the topic, with its protocol and settings (filter policy, DLQ, raw delivery) | an SQS queue, a Lambda function, an email address |
Push vs pull is the first exam distinction. SQS is pull: consumers call ReceiveMessage and take messages when they are ready (lesson 13.1). SNS is push: it delivers to each endpoint as soon as the message is published, and nobody has to ask.
SNS is not a store. Once a message has been delivered (or retries run out), a standard topic keeps nothing. If a receiver needs to process later, retry its own work or survive a long outage, it should be an SQS queue subscribed to the topic. That is the fan-out pattern, below.
#Who publishes to SNS
Your own code publishes with the SDK or CLI, but many AWS services can publish to a topic directly, which is why SNS is the “notification bus” of AWS. The slides list a typical set:
- CloudWatch alarms (“CPU above 80 %” → on-call email and SMS; lesson 19.3),
- AWS Budgets (the billing alert from lesson 1.4),
- Auto Scaling group notifications (instance launched, terminated or failed, lesson 6.5),
- S3 event notifications (lesson 10.7),
- Lambda (from your function code, or as an asynchronous invocation destination),
- CloudFormation stack state changes, AWS DMS replication events, RDS event subscriptions (failover, backup, maintenance), DynamoDB (for example through CloudWatch alarms), and many more.
A service that publishes to your topic needs permission in the topic’s access policy (see security, below).
#Who can subscribe
| Group | Subscriber (protocol) | Typical use |
|---|---|---|
| AWS services (application-to-application, A2A) | Amazon SQS queue | Durable fan-out to workers; the most important one |
| AWS Lambda function | Run code on every message, invoked asynchronously | |
| Amazon Data Firehose stream | Store messages in S3, Redshift, OpenSearch, Splunk… | |
| Custom endpoints | HTTP / HTTPS | Webhooks, partner or third-party APIs |
| People (application-to-person, A2P) | Email / email-JSON | Alerts to an inbox |
| SMS text messages | OTPs, order status, alerts to phones | |
| Mobile push | Notifications to iOS, Android and Fire apps through APNs, FCM, ADM and others |
Things that cannot subscribe directly: S3 buckets (use Firehose), Kinesis Data Streams, DynamoDB tables, EC2 instances (give them an HTTP endpoint or, better, an SQS queue). The exam likes to offer these as wrong answers.
Some details people miss:
- Email and HTTP/S subscriptions must be confirmed. SNS sends a confirmation message; until someone clicks the link (or the endpoint calls
ConfirmSubscription), the subscription is pending confirmation and receives nothing. - Email is for operational alerts, not for marketing or customer email at scale: it is limited to 10 messages per second per email subscription, and the sender address and format are SNS’s. For real customer email, use Amazon Simple Email Service.
- SMS is delivered through AWS End User Messaging SMS (formerly Amazon Pinpoint SMS). New accounts start in an SMS sandbox with a $1 monthly spend limit, and many countries require a registered sender ID or number before messages are delivered.
#Standard and FIFO topics
Like SQS, SNS has two topic types:
- Standard topics: nearly unlimited throughput, at-least-once delivery and best-effort ordering. Every subscriber type is supported. This is the default and the right answer for notifications and most fan-out.
- FIFO topics (name ends in
.fifo): strict ordering per message group and deduplication, at limited throughput, and only SQS queues as subscribers. They get their own section below.
#Limits worth knowing
| Item | Standard topic | FIFO topic |
|---|---|---|
| Topics per account | 100,000 | 1,000 |
| Subscriptions per topic | 12,500,000 | 100 |
| Message size | 256 KiB by default (body + attributes) | same |
Messages per PublishBatch call | 10 | 10 |
| Publish throughput | A soft per-account quota per Region (for example 30,000 messages/s in us-east-1, 1,500 in Mumbai or Singapore) | 300 messages/s per message group; 3,000 messages/s or 20 MB/s per topic by default |
| Filter policies | 200 per topic, 10,000 per account | same |
Side note, verified in the AWS docs: since September 2026 a topic can accept payloads up to 1 MiB if you raise its MaximumMessageSize attribute, but only when every subscription is SQS, Lambda or Firehose and there are at most 100 subscriptions. Beyond that, the SNS Extended Client Library (Java, Python) stores the payload in S3 and publishes a pointer, up to 2 GB. For the exam, the SNS message limit is still 256 KB.
#How to publish
The slides name two ways:
- Topic publish (the normal case, with the SDK or CLI): create a topic, create one or many subscriptions, publish to the topic. Every subscription gets a copy.
PublishBatchsends up to 10 messages in one call, which cuts API calls and cost. - Direct publish (mobile apps): create a platform application with your credentials for a push service (APNs for Apple, FCM for Google, ADM for Amazon devices, plus Baidu and Windows push services), register each device token as a platform endpoint, then publish straight to one endpoint’s ARN, with no topic. This is how you send “your rider is outside” to one customer’s phone. Mobile endpoints can also be subscribed to a topic for broadcasts (“Eid offer: 20 % off”).
Each published message can carry up to 10 message attributes (name, type String, String.Array, Number or Binary, and value). Attributes are metadata outside the body; filter policies, below, use them.
Pricing, roughly: about $0.50 per million publish requests for standard topics (each 64 KB chunk counts as one request), no per-message charge for delivery to SQS and Lambda, and per-delivery prices for HTTP, email, SMS and mobile push. Attribute-based filtering is free; payload-based filtering is billed per GB scanned.
#SNS security
The slides group SNS security into encryption and access control; it mirrors SQS (lesson 13.1) and S3 (lessons 10.2 and 10.8).
Encryption
- In flight: the SNS API is HTTPS. You can force it with a topic policy that denies requests where
aws:SecureTransportis false. Topics with server-side encryption accept only HTTPS requests anyway. - At rest: server-side encryption with KMS keys (the AWS managed key
aws/sns, or a customer managed key). It is off by default on standard topics, unlike SQS, which encrypts new queues with SSE-SQS by default. SSE encrypts the message body only: topic metadata and message attributes are not encrypted, so never put secrets in attributes. (That is also why filtering on attributes works on an encrypted topic.) - Client-side encryption: if the client wants to encrypt and decrypt the payload itself, SNS just carries ciphertext.
Access control
- IAM policies on users and roles decide who may call the SNS API (
sns:Publish,sns:Subscribe,sns:CreateTopic…), as in chapter 2. - SNS access policies are resource-based policies on the topic, similar to S3 bucket policies (lesson 2.2 on resource-based policies). You need them for:
- cross-account access: another account publishing to, or subscribing to, your topic;
- AWS services that publish to the topic, such as S3, CloudWatch or Budgets: allow the service principal (for example
s3.amazonaws.com) and limit it withaws:SourceArnandaws:SourceAccount.
- If the topic uses a KMS key, a publishing service also needs
kms:GenerateDataKeyandkms:Decrypton that key. You cannot edit the policy of the AWS managed keyaws/sns, so a topic that S3 or CloudWatch publishes to needs a customer managed key.
Side note: message data protection (2022) lets a topic policy audit, mask or block sensitive data such as card numbers or national ID numbers in messages as they pass through. It is useful for compliance, and it is not a substitute for encryption.
#SNS + SQS: the fan-out pattern
#Push once, receive in every queue
Fan-out is the most popular SNS architecture and one of the most tested patterns in the exam. A publisher sends a message once to an SNS topic; several SQS queues are subscribed; SNS pushes a copy into every queue at the same moment; each queue’s own workers process their copy asynchronously and in parallel. Like an electric fan, the same air goes in every direction at once.
Fan-out: one topic, three queues
An online shop publishes “order placed” once. Three SQS queues are subscribed: inventory, notifications and fraud. Each queue has its own workers.
Scenario
Push once into SNS, receive in every subscribed queue, process in parallel.
The shop publishes one “order placed” message, order 1036. It makes one call, whatever the number of teams that care about orders.
#What the queues add
SNS alone delivers and forgets. Putting an SQS queue behind each subscription adds what SNS does not have (the slides list the first three):
- Persistence: the message waits in the queue (4 days by default, up to 14) until a worker processes it. A consumer that crashes loses nothing; this is the “no data loss” of the notes.
- Delayed processing: each consumer works at its own pace, and a delay queue or a nightly batch is fine.
- Retries of work: a worker that fails simply does not delete the message; it reappears after the visibility timeout, and after
maxReceiveCountattempts it goes to the queue’s own DLQ (lesson 13.2). - Independent scaling: each queue can drive its own Auto Scaling group or Lambda concurrency (lesson 13.1).
- New consumers over time: a new team subscribes a new queue; publisher and existing queues stay as they are.
SNS → SQS delivery itself is very reliable: SQS is an AWS-managed endpoint, retried for up to 23 days (see “Delivery, retries and dead-letter queues”).
#The queue must allow the topic to write
An SQS queue only accepts messages from principals its access policy allows. When you subscribe a queue in the console, the console adds the statement; when you use the CLI, CloudFormation or Terraform, you must add it, or every delivery to that queue fails with “access denied”:
{
"Version": "2012-10-17",
"Statement": [{
"Sid": "AllowOrdersTopic",
"Effect": "Allow",
"Principal": { "Service": "sns.amazonaws.com" },
"Action": "sqs:SendMessage",
"Resource": "arn:aws:sqs:ap-southeast-1:111122223333:inventory-example",
"Condition": { "ArnEquals": { "aws:SourceArn": "arn:aws:sns:ap-southeast-1:111122223333:orders-example" } }
}]
}
The aws:SourceArn condition matters: without it, any SNS topic in any account could write to your queue.
If the queue is encrypted with SSE-KMS, SNS must also be able to use the key. The AWS managed key aws/sqs cannot be shared, so use a customer managed key whose key policy allows sns.amazonaws.com to call kms:GenerateDataKey and kms:Decrypt. (A queue with the default SSE-SQS encryption needs nothing extra.)
#Across Regions and accounts
- Cross-Region delivery works for SQS queues and Lambda functions: the topic in ap-southeast-1 can deliver to a queue in eu-west-1. You run the subscribe command in the topic’s Region, and pay normal inter-Region data transfer. (Opt-in Regions such as Bahrain or Hong Kong need a Region-specific service principal in the queue policy.)
- Cross-account fan-out needs two permissions: the topic policy must allow the other account to
sns:Subscribe(or the topic owner subscribes the queue), and the queue policy must allow the topic tosqs:SendMessage. A subscription created by the topic owner for a queue in another account must be confirmed by the queue’s owner; one created by the queue’s owner needs no confirmation.
#Raw message delivery
By default, SNS wraps your message in a JSON envelope (Type, MessageId, TopicArn, Timestamp, Message, MessageAttributes, signature fields), so an SQS consumer finds your order JSON as an escaped string inside the Message field. Turn on raw message delivery on the subscription (for SQS, HTTP/S and Firehose) and the queue receives exactly what was published, with SNS message attributes turned into SQS message attributes. Consumers that were written for messages sent straight to SQS then work unchanged.
#Two classic fan-out applications
#S3 events to many queues
Lesson 10.7 explained S3 event notifications and their overlap rule: two rules for the same event type with overlapping prefix and suffix (for example ObjectCreated on images/) cannot both exist, so native notifications send one event to one destination. If several queues or functions need the same event, point the one rule at a standard SNS topic in the same Region and subscribe them all: that is fan-out. The topic’s access policy must allow s3.amazonaws.com to publish, limited to the bucket with aws:SourceArn and aws:SourceAccount. (A FIFO topic cannot be an S3 destination. The other modern answer is to turn on EventBridge for the bucket, where any number of rules can match the same event; chapter 19.)
The notes’ classic question belongs here too: “send an email immediately when a file is uploaded to S3” → an S3 event notification to an SNS topic with an email subscription.
#SNS to S3 through Firehose
SNS cannot write to S3 itself, and S3 is not a subscriber type. But Amazon Data Firehose (called Kinesis Data Firehose on the slides; renamed in 2024) is. A Firehose subscription lets SNS push every message into a Firehose stream, which buffers them (by size or time) and writes them as objects to S3, or to any Firehose destination: Redshift, OpenSearch, Splunk, HTTP endpoints, Apache Iceberg tables (lesson 13.6). This is the standard way to archive a topic’s messages for audit or analytics.
- The subscription needs an IAM role that lets SNS write to the stream (
firehose:PutRecordand related actions). - A standard topic can have up to 5 Firehose subscriptions per subscription owner.
- Turn on raw message delivery to store only your payload, not the SNS envelope.
- Firehose delivery is near real time (buffering), not instant.
S3 events to many targets, and SNS into S3
A Dhaka hospital uploads scan images to a bucket. Two teams need every upload event, and compliance wants every message archived in S3.
Scenario
Native S3 notifications: one event type and prefix, one destination.
The thumbnail team adds a notification rule: object-created events on scans/ to their SQS queue. Every upload now lands in the queue.
#FIFO topics
#Order and deduplication, end to end
A standard topic may deliver a message twice and in a different order from publishing. For many notifications that is fine. For a ledger, a stock count or the steps of a payment, it is not. An SNS FIFO topic (the name must end in .fifo) brings the guarantees of SQS FIFO (lesson 13.3) to pub/sub:
- Ordering by message group ID. Every message carries a
MessageGroupId; messages in the same group are delivered in the order they were published. Different groups are independent and are delivered in parallel. - Deduplication. A message with the same message deduplication ID as one published in the last 5 minutes is accepted but not delivered again. With content-based deduplication turned on, SNS uses a hash of the message body as the deduplication ID, so you do not have to set one.
- Subscribers: SQS only. FIFO topics deliver to SQS FIFO queues and, since 2023, to SQS standard queues too. They cannot deliver to Lambda, HTTP/S, email, SMS, mobile push or Firehose. A Lambda consumer reads a FIFO queue instead.
- A standard queue behind a FIFO topic receives the messages in order, but a standard queue does not keep order or prevent duplicates for its consumer. Use it for subscribers that do not care.
#SNS FIFO + SQS FIFO fan-out
When you need fan-out + ordering + deduplication, the slides’ answer is an SNS FIFO topic with SQS FIFO queues subscribed. Each queue receives every message of every group in order and exactly once (within the deduplication window), and each team’s consumers process their own copy in order.
#Throughput
The slides say FIFO topics have “the same throughput as SQS FIFO”. The current numbers:
- 300 messages per second per message group, and by default 3,000 messages per second (or 20 MB/s) per topic, with deduplication checked across the whole topic.
- High-throughput mode (January 2025): set the topic’s
FifoThroughputScopetoMessageGroup. Ordering stays per group, deduplication becomes per group, and the topic can use the account’s Regional publish quota (for example 30,000 messages/s in us-east-1). Spread messages over many groups to use it. - A FIFO topic has at most 100 subscriptions.
So throughput grows with the number of groups: with 5 busy groups, at most 5 × 300 = 1,500 messages/s; with 20 groups, the 3,000 per topic default becomes the limit.
#Archive and replay
Side note (October 2023): a FIFO topic can archive every message it receives for 1 to 365 days (an archive policy on the topic), and a subscriber can replay archived messages from a chosen start time (a replay policy on its subscription). A team that corrupted its data with a bug can rebuild it; a new subscriber can catch up on history. Replay costs extra and works only for FIFO topics (application-to-application). For the exam, “replay a stream of data” still points to Kinesis (lesson 13.5).
FIFO topic: order and no duplicates
A mobile wallet publishes the events of each payment in order: created, paid, settled. The ledger must apply them exactly in that order and exactly once.
Scenario
All events of one payment share a message group ID, so they stay in order end to end.
The wallet publishes three events for payment P-77 with message group ID P-77: 1 created, 2 paid, 3 settled.
Self-checkQuestion
A payments platform publishes created, paid and settled events for each payment. Three teams must each receive every event, in order per payment, with no duplicates, and each team processes at its own pace. What should the architect use?
#Message filtering
#Why filter
Normally every subscription of a topic receives every message. Often that is not what you want: the refunds team does not care about placed orders, the premium desk only wants premium ones. Without filtering, each consumer must receive everything, check in its own code whether the message is relevant, and delete the rest. That wastes compute, SQS requests and money, and it spreads routing logic over many code bases.
Message filtering lets each subscription say which messages it wants. SNS checks every message against the subscription’s filter policy and delivers only the matching ones. Messages that do not match are simply not delivered to that subscription (they still go to the others).
#Attributes and filter policies
- The publisher adds message attributes to each message, metadata outside the body, for example
state = placedandorder_type = premium. - Each subscription gets a filter policy: a small JSON document with the attribute names it cares about and the values it accepts.
{
"state": ["placed"],
"order_type": ["premium", "gold"],
"amount": [{ "numeric": [">=", 10000] }],
"city": [{ "anything-but": ["Dhaka"] }]
}
The matching rules:
- No policy → every message. The slides make this point: a subscription without a filter policy receives everything.
- AND across keys: every key in the policy must match.
- OR inside a list: any one of the values listed for a key is enough (
premiumorgold). An$oroperator can also combine whole alternative conditions. - A missing attribute never matches a key, except with
{"exists": false}. - String matching is case-sensitive:
Placeddoes not matchplaced(unless you useequals-ignore-case). - Attributes that the policy does not mention are ignored.
| Operator | Example | Matches |
|---|---|---|
| Exact string | "state": ["placed"] | state is exactly placed |
| anything-but | "city": [{"anything-but": ["Dhaka"]}] | city exists and is not Dhaka |
| prefix / suffix | "sku": [{"prefix": "MED-"}] | values starting with MED- |
| equals-ignore-case | "state": [{"equals-ignore-case": "placed"}] | placed, Placed, PLACED |
| numeric | "amount": [{"numeric": [">", 0, "<=", 5000]}] | 0 < amount ≤ 5,000 |
| exists | "coupon": [{"exists": true}] | the attribute is present |
| IP address | "source_ip": [{"cidr": "10.0.0.0/24"}] | addresses in that range |
| wildcard | "file": [{"wildcard": "*.jpg"}] | values matching the pattern |
Constraints to remember: at most 5 keys per policy, at most 150 combinations (multiply the number of values of each key: 3 × 5 × 10 = 150 is the limit), 256 KB per policy, 200 policies per topic. A new or changed policy can take up to 15 minutes to take full effect. Filter policies work on standard and FIFO topics.
#Attribute-based and payload-based filtering
- Attribute-based (the default; the subscription’s
FilterPolicyScopeisMessageAttributes): the policy is matched against the message attributes only,String,String.ArrayandNumbertypes. Policies cannot be nested. This is what exam questions usually describe. - Payload-based (since November 2022;
FilterPolicyScope=MessageBody): the policy is matched against the JSON body itself, including nested keys, for example{"order": {"state": ["placed"]}}. Use it when publishers you do not control (another team, an AWS service) put everything in the body and set no attributes. The body must be valid JSON, and it costs a small fee per GB scanned.
Filter policies: each subscriber picks its messages
Every order event carries attributes. The placed queue has the policy state = placed, the cancelled queue state = cancelled, and the analytics queue has no policy at all.
Scenario
SNS checks the message against each subscription’s policy and delivers only where it matches.
Message attributes
order
1036
state
placed
order_type
premium
The order service publishes order 1036 with the attributes state = placed and order_type = premium. The body is the full order; the attributes are a small label on the outside.
Try the rules yourself: build a message and see which of the eight subscriptions receive it.
Filter policy lab
Build one order message for the orders topic and see which of its eight subscriptions receive it. Try the traps: a capital letter, a missing attribute, the fields only in the body.
1. The message
2. Who receives it
Pick values above; nothing is sent until you change one.
#One topic with filters, or many topics?
- One topic + filter policies when the messages are the same kind of event and receivers want different subsets. Publishers stay simple (one topic), and new subsets are just new policies.
- Separate topics when the events are really different (orders vs inventory alarms), have different owners or permissions, or need different topic types (standard vs FIFO).
- If routing rules become complex (many sources, content transformation, schedules, SaaS sources), EventBridge rules (chapter 19) are the bigger tool; SNS filtering is for fast, simple, high-volume fan-out.
#Delivery, retries and dead-letter queues
#How SNS retries
When a delivery fails because the endpoint is unavailable (a server-side error: HTTP 5xx, 429, a throttled Lambda), SNS retries according to a delivery policy that depends on the protocol:
| Endpoint | Retry policy | Can you change it? |
|---|---|---|
| SQS, Lambda (AWS-managed endpoints) | 3 immediate, 2 at 1 s, 10 with backoff up to 20 s, then 100,000 at 20 s: 100,015 attempts over 23 days | No |
| Email, SMS, mobile push | 50 attempts over 6 hours | No |
| HTTP / HTTPS | Default: 3 retries, 20 s apart. Custom policy on the topic or subscription: up to 100 retries, backoff function (linear, arithmetic, geometric, exponential), total retry time at most 1 hour, plus an optional throttle (maxReceivesPerSecond) | Yes, only this one |
When the delivery policy is used up, SNS discards the message, unless the subscription has a dead-letter queue.
Client-side errors are different: the endpoint was deleted, the queue or function policy no longer allows SNS, the KMS key is unusable, or an HTTP endpoint answers 4xx (other than 429). SNS does not retry these at all, because a retry would fail the same way.
Retries mean an endpoint can receive the same message more than once (standard topics are at-least-once): make consumers idempotent, for example by remembering the MessageId.
#Subscription dead-letter queues
A dead-letter queue (DLQ) for SNS is an ordinary SQS queue attached to a subscription (not to the topic) with a redrive policy (deadLetterTargetArn). Messages that fail with a client-side error, or that run out of retries, go there instead of being lost. Rules:
- The DLQ must be in the same account and Region as the subscription.
- A FIFO topic’s subscription needs a FIFO DLQ; a standard topic’s, a standard queue.
- The DLQ’s access policy must allow SNS to send, and if it is encrypted, a customer managed KMS key must allow SNS.
- Set the DLQ’s retention to the maximum, 14 days, and put a CloudWatch alarm on its
ApproximateNumberOfMessagesVisible. - Failed deliveries do not disable a subscription. Watch the
NumberOfNotificationsFailedmetric, and turn on delivery status logging (to CloudWatch Logs, for SQS, Lambda, HTTP/S, Firehose, SMS and mobile push).
This is the “SNS also has DLQs” of the notes’ DLQ section: SQS has DLQs for messages consumers keep failing (lesson 13.2), SNS for messages it could not deliver, and Lambda for asynchronous invocations that keep failing (chapter 15).
When delivery fails: retries and the subscription DLQ
A courier partner receives order events on an HTTPS webhook. Watch what SNS does when the webhook is down, when it never comes back, and when the error is on your side.
Scenario
Server-side errors (5xx, 429) are retried according to the delivery policy.
An order is published. The topic has an HTTPS subscription for the courier partner’s webhook.
#SNS and SQS side by side
The notes end their SQS and SNS part with a recap for the night before the exam. Here it is, with the details from lessons 13.1–13.4:
| SQS | SNS | |
|---|---|---|
| Model | Queue: each message to one consumer | Pub/sub: each message to every subscription |
| Delivery | Pull (consumers poll) | Push |
| Keeps messages | Yes, up to 14 days, until deleted | No (standard); FIFO topics can archive for replay |
| Typical words | Decouple, buffer, absorb spikes, asynchronous, worker | Notify, alerts, email/SMS, push notifications, many subscribers |
| Failure handling | Visibility timeout, maxReceiveCount, DLQ | Delivery retries per protocol, subscription DLQ |
| Ordering | Standard: best effort; FIFO: per group | Standard: best effort; FIFO: per group |
| Together | Fan-out: 1 SNS topic → many SQS queues (parallel processing) | Filtering: each subscription receives only matching messages (saves compute) |
Kinesis, the third model (a replayable stream), is lesson 13.5, and the full SQS vs SNS vs Kinesis comparison is lesson 13.7.
#What goes wrong
| Symptom | Likely cause | Fix |
|---|---|---|
| A subscribed SQS queue never receives messages | The queue’s access policy does not allow sns.amazonaws.com (subscribed with CLI/IaC) | Add sqs:SendMessage for the SNS principal with aws:SourceArn = topic |
| Deliveries to an encrypted queue fail | Queue uses the AWS managed key aws/sqs, which SNS cannot use | Customer managed key whose policy allows SNS kms:GenerateDataKey and kms:Decrypt |
| S3 cannot save a notification to the topic | Topic policy does not allow s3.amazonaws.com; topic is FIFO; topic in another Region; KMS key policy | Fix the topic policy; use a standard topic in the bucket’s Region; customer managed key |
| Email subscribers get nothing | Subscription still pending confirmation | Click the confirmation link; check spam |
| The consumer cannot parse the message | SNS envelope: the payload is a string inside Message | Turn on raw message delivery, or unwrap the envelope |
| A queue with a filter policy receives nothing | Attribute missing, wrong type, wrong case, or the fields are only in the body | Set the attributes; match case; use payload-based filtering; wait up to 15 minutes after a change |
| Messages to an HTTP endpoint were lost during an outage | Default HTTP policy (3 retries, 20 s) ran out; no DLQ | Subscription DLQ; custom delivery policy; SQS queue in between |
| A webhook processes the same order twice | At-least-once delivery and retries after timeouts | Idempotent consumer keyed on MessageId; or FIFO topic + FIFO queue |
Publish to a FIFO topic is throttled | 300 messages/s per group, 3,000 per topic | More message groups; high-throughput mode; batching |
| Lambda cannot be subscribed to a FIFO topic | FIFO topics deliver only to SQS | Subscribe an SQS FIFO queue and trigger Lambda from it |
Publish fails with InvalidParameter on large messages | Payload over 256 KiB (body + attributes) | Extended Client Library with S3; or raise MaximumMessageSize if subscribers allow |
| SMS not delivered abroad | Sandbox, spend limit, or no registered sender ID or number | Leave the sandbox, raise the limit, register an origination identity |
#SNS in system design
- Notifications to people. CloudWatch alarms, Budgets and ASG events → a topic → email, SMS, chat tools through Lambda or HTTPS. The most common first use of SNS in every account.
- Event fan-out between services. One domain event (
order-placed) → a standard topic → one SQS queue per consuming service. Producers and consumers deploy and scale independently; the classic choreography style of microservices. - Fan-out + filtering. One topic per kind of event, with filter policies so each service gets only its share. Cheaper and simpler than many topics.
- Ordered fan-out. FIFO topic + FIFO queues for ledgers, inventory and state machines; group ID = entity ID.
- Multi-Region and multi-account. A topic in one Region delivering to queues in a DR Region or in other accounts (cross-account policies on both sides).
- Archiving. A Firehose subscription for an audit trail in S3; FIFO archive and replay when consumers must rebuild state.
- Buffer fragile endpoints. Put SQS between SNS and anything that can be down for long: a partner webhook, an on-premises system.
- Know when to pick something else. Many sources, rich routing and schemas → EventBridge (chapter 19). Replay and many readers of a high-volume stream → Kinesis (lesson 13.5). Legacy apps speaking AMQP or MQTT → Amazon MQ (lesson 13.7).
#Try it yourself
All commands run in ap-southeast-1; names end in -example. Output is shortened.
# 1. A standard topic and two queues
aws sns create-topic --name orders-example
# { "TopicArn": "arn:aws:sns:ap-southeast-1:111122223333:orders-example" }
aws sqs create-queue --queue-name inventory-example
aws sqs create-queue --queue-name refunds-example
# { "QueueUrl": "https://sqs.ap-southeast-1.amazonaws.com/111122223333/inventory-example" }
# 2. Let the topic write to each queue (policy.json is the queue policy shown in the lesson)
aws sqs set-queue-attributes \
--queue-url https://sqs.ap-southeast-1.amazonaws.com/111122223333/inventory-example \
--attributes file://inventory-policy.json
# 3. Subscribe the queues: raw delivery, and a filter policy on the refunds queue
aws sns subscribe --topic-arn arn:aws:sns:ap-southeast-1:111122223333:orders-example \
--protocol sqs --notification-endpoint arn:aws:sqs:ap-southeast-1:111122223333:inventory-example \
--attributes RawMessageDelivery=true
aws sns subscribe --topic-arn arn:aws:sns:ap-southeast-1:111122223333:orders-example \
--protocol sqs --notification-endpoint arn:aws:sqs:ap-southeast-1:111122223333:refunds-example \
--attributes '{"RawMessageDelivery":"true","FilterPolicy":"{\"state\":[\"cancelled\",\"declined\"]}"}'
# { "SubscriptionArn": "arn:aws:sns:ap-southeast-1:111122223333:orders-example:6b0e71bd-7e97-4d97-80ce-4a0994e55286" }
# 4. An email subscription stays pending until the link is clicked
aws sns subscribe --topic-arn arn:aws:sns:ap-southeast-1:111122223333:orders-example \
--protocol email --notification-endpoint ops@example.com
# { "SubscriptionArn": "pending confirmation" }
# 5. Publish a placed order with attributes: inventory gets it, refunds does not
aws sns publish --topic-arn arn:aws:sns:ap-southeast-1:111122223333:orders-example \
--message '{"order":1036,"item":"pencil","qty":4}' \
--message-attributes '{"state":{"DataType":"String","StringValue":"placed"}}'
# { "MessageId": "f1d0a8e2-3c51-5f1a-9b8e-2a7c4d0e9b11" }
aws sqs receive-message --wait-time-seconds 10 \
--queue-url https://sqs.ap-southeast-1.amazonaws.com/111122223333/inventory-example
# "Body": "{\"order\":1036,\"item\":\"pencil\",\"qty\":4}" (raw: no SNS envelope)
aws sqs receive-message --wait-time-seconds 10 \
--queue-url https://sqs.ap-southeast-1.amazonaws.com/111122223333/refunds-example
# (no output: filtered out)
# 6. Switch a subscription to payload-based filtering, and give it a DLQ
aws sns set-subscription-attributes --subscription-arn <refunds-subscription-arn> \
--attribute-name FilterPolicyScope --attribute-value MessageBody
aws sns set-subscription-attributes --subscription-arn <refunds-subscription-arn> \
--attribute-name RedrivePolicy \
--attribute-value '{"deadLetterTargetArn":"arn:aws:sqs:ap-southeast-1:111122223333:refunds-dlq-example"}'
# 7. A FIFO topic with content-based deduplication, and an ordered publish
aws sns create-topic --name payments-example.fifo \
--attributes FifoTopic=true,ContentBasedDeduplication=true
aws sns publish --topic-arn arn:aws:sns:ap-southeast-1:111122223333:payments-example.fifo \
--message '{"payment":"P-77","event":"paid"}' --message-group-id P-77
# { "MessageId": "…", "SequenceNumber": "10000000000000003000" }
# 8. See every subscription and its state
aws sns list-subscriptions-by-topic \
--topic-arn arn:aws:sns:ap-southeast-1:111122223333:orders-example
Things to notice: step 5 shows filtering and raw delivery together (try it without RawMessageDelivery and compare the envelope); step 4 shows why email alerts sometimes “do not work”; and publishing the same body twice within 5 minutes to the FIFO topic in step 7 delivers it only once.
#Summary
Key takeaways
- Direct calls to many receivers are slow, fragile and coupled. SNS is AWS’s managed, push-based pub/sub service: a publisher sends once to a topic, and every subscription gets a copy. Like a YouTube channel and its subscribers.
- Subscribers: SQS, Lambda, Data Firehose (A2A); HTTP/S; email, SMS, mobile push (A2P). Not S3, Kinesis Data Streams or EC2 directly. Email and HTTP/S must be confirmed. Many AWS services publish to SNS (CloudWatch alarms, Budgets, ASG, S3 events, RDS, DMS, CloudFormation…).
- Limits: 12,500,000 subscriptions per standard topic (100 for FIFO), 100,000 topics per account (1,000 FIFO), 256 KB messages (1 MiB opt-in since 2026 for SQS/Lambda/Firehose-only topics; Extended Client Library to 2 GB).
- Publish: topic publish (SDK/CLI,
PublishBatchof 10) or direct publish to a mobile platform endpoint (APNs, FCM, ADM…). - Security: HTTPS in flight; SSE with KMS at rest (off by default, body only, attributes not encrypted); client-side encryption; IAM for API calls; topic access policies for cross-account and AWS services such as S3.
- Fan-out: SNS topic → many SQS queues: fully decoupled, no data loss, persistence, delayed processing, retries, add queues later. The queue access policy must allow the topic; encrypted queues need a customer managed key; works cross-Region and cross-account; raw message delivery removes the envelope.
- Applications: S3 events to many targets (one rule → topic), and SNS → Firehose → S3 for archiving.
- FIFO topics: order per message group ID, deduplication (5 minutes, ID or content-based), SQS-only subscribers (FIFO or standard), 300/s per group and 3,000/s per topic (high-throughput mode for more), archive and replay. SNS FIFO + SQS FIFO = fan-out + ordering + deduplication.
- Filtering: a JSON filter policy per subscription; no policy = everything; AND across keys, OR within a list; case-sensitive; missing attribute = no match; attribute-based (default) or payload-based. Saves compute and moves routing out of consumer code.
- Retries: SQS/Lambda 100,015 attempts over 23 days; email/SMS/push 50 over 6 hours; HTTP/S default 3 retries, customizable up to an hour. Client-side errors are not retried. A subscription DLQ (SQS, same account and Region) keeps what would be lost.
Answer on your own first, then read the explanation, even when you got it right.
Self-checkQuestion
Which statement describes Amazon SNS?
Self-checkQuestion
Which two can be subscribed directly to a standard SNS topic?
Choose 2
Self-checkQuestion
What is the default maximum number of subscriptions on one standard SNS topic?
Self-checkQuestion
A ride-hailing app must send a push notification to one specific rider’s phone when a customer is waiting. What is the SNS way to do this?
Self-checkQuestion
An online shop must update inventory, send a confirmation email and run a fraud check for every order. The three tasks must run in parallel, independently, and no order may be lost if one of the services is down for an hour. What should the architect build?
Self-checkQuestion
An engineer subscribed a new SQS queue to a topic with the AWS CLI. The other queues on the topic receive messages, but the new one never does. What is the most likely cause?
Self-checkQuestion
A team encrypts its SQS queue with the AWS managed key aws/sqs and subscribes it to an SNS topic. The access policy is correct, but deliveries still fail. What should they do?
Self-checkQuestion
A photo bucket must send every object-created event under uploads/ to two SQS queues owned by different teams, using native S3 event notifications. What should the architect do?
Self-checkQuestion
A compliance team needs a copy of every message published to an SNS topic stored in S3, in batched files, without writing code. What is the simplest solution?
Self-checkQuestion
Which statement about SNS FIFO topics is correct?
Self-checkQuestion
Which two statements about SNS FIFO topics are correct?
Choose 2
Self-checkQuestion
A FIFO topic in default mode receives payment events spread evenly over 5 busy message groups. What is the highest sustained publish rate it can reach?
Self-checkQuestion
A wallet API publishes a paid event to a FIFO topic with deduplication ID pay-77-2, times out, and retries with the same ID 2 minutes later. What happens?
Self-checkQuestion
A topic has three subscriptions. The first has the filter policy state = placed, the second state = cancelled, and the third has no filter policy. A message is published with the attribute state = declined. Which subscriptions receive it?
Self-checkQuestion
A reporting microservice only needs high-value orders from a busy orders topic. Today it receives every order and discards 95 percent of them in code, which costs compute and SQS requests. What change is the most efficient?
Self-checkQuestion
A subscription has the policy {state: [placed, cancelled], city: [Dhaka]}. Which message is delivered?
Self-checkQuestion
A publisher sets the attribute state = Placed. The subscription’s filter policy is state = placed. Messages never arrive. Why, and what is a fix?
Self-checkQuestion
Another team’s service publishes order events to your topic as nested JSON in the body, with no message attributes, and will not change. Your subscription must receive only orders whose order.state is placed. What should you do?
Self-checkQuestion
A topic receives 1,000,000 orders a day. Four SQS queues are subscribed, and each needs only its own quarter of the orders. How many messages a day land in the queues without filter policies, and with a correct filter policy on each subscription?
Self-checkQuestion
An engineer writes a filter policy with three keys: state lists 6 values, city lists 5 values and channel lists 6 values. SNS rejects the policy. Why?
Self-checkQuestion
A partner’s HTTPS webhook subscribed to a topic was down for two hours. Messages from that period never arrived, and the subscription has the default delivery policy. Which two changes would have prevented the loss?
Choose 2
Self-checkQuestion
A Lambda function subscribed to a topic was deleted by mistake. What does SNS do with new messages for that subscription?
Self-checkQuestion
How long does SNS keep retrying a delivery to a subscribed SQS queue that keeps returning server-side errors?
Self-checkQuestion
Which two statements about SNS subscription dead-letter queues are correct?
Choose 2
Self-checkQuestion
Which two statements about SNS security are correct?
Choose 2
Self-checkQuestion
Account A owns an orders topic. Account B wants its own SQS queue to receive every order. Which combination is required?
Self-checkQuestion
A company wants an email sent to its records officer immediately whenever a file is uploaded to a specific S3 bucket, with no servers to manage. What is the simplest design?
Self-checkQuestion
An SQS consumer that used to read orders sent straight to SQS now reads them through an SNS fan-out, and it fails to parse them: the body contains a type, a message ID, the topic ARN and the order as an escaped string. What is the simplest fix?
Self-checkQuestion
A topic has SQS and email subscriptions. The team must now publish 600 KB reports through it. What should they do?
Self-checkQuestion
Which statement about Amazon SNS is NOT true?