SNS & SQS via SDK Best Practices
This is the checklist to run against any messaging system built on SNS and SQS, beyond the Core intro's single topic and queue.
Search across all documentation pages
This is the checklist to run against any messaging system built on SNS and SQS, beyond the Core intro's single topic and queue.
Each item is a rule stated positively, with a one-line rationale. Work top to bottom - fan-out and permissions first, then ordering, failure handling, throughput, and filtering.
sns.amazonaws.com to SendMessage, scoped with aws:SourceArn to the topic.Subscribe needs the ARN as the endpoint; the URL is only for SendMessage/ReceiveMessage.PendingConfirmation means you subscribed the wrong protocol..fifo suffix and FifoTopic/FifoQueue attribute cannot be added or removed after the fact.MessageDeduplicationId values.# --- Python (boto3) ---
# FIFO naming and attribute are both required, set once at creation.
queue_url = sqs.create_queue(
QueueName="orders.fifo",
Attributes={"FifoQueue": "true", "ContentBasedDeduplication": "true"},
)["QueueUrl"]// --- TypeScript (AWS SDK v3) ---
// FIFO naming and attribute are both required, set once at creation.
const { QueueUrl } = await sqs.send(new CreateQueueCommand({
QueueName: "orders.fifo",
Attributes: { FifoQueue: "true", ContentBasedDeduplication: "true" },
}));ApproximateNumberOfMessagesVisible catches silent pileups before they go unnoticed for days.SendMessageBatch/DeleteMessageBatch cut request count (and cost) versus one-at-a-time calls.WaitTimeSeconds (up to 20) so receives wait for messages instead of returning empty and billing anyway.ChangeMessageVisibility instead of inflating the default for everyone.Failed alongside Successful.FilterPolicy rules scales better than a topic per event type.eventType matches nothing if publishers never set that attribute.MessageAttributes (default) and MessageBody are not interchangeable - set the scope explicitly if you filter on the body.Publish succeeds regardless of whether any given subscriber's filter matches.With permissions and wiring: get the queue policy and ARN-based subscription right first. A correctly wired fan-out with no ordering, filtering, or DLQ is still functional; a misconfigured queue policy silently drops every delivery.
When downstream logic genuinely depends on event order for a given entity, or when duplicate sends from a retrying producer would corrupt state. If neither applies, standard topics and queues are simpler and faster.
No dead-letter queue. Without one, a poison message retries indefinitely, burning consumer capacity, or a low maxReceiveCount discards messages that would have succeeded on retry.
Delete only after successful processing using the correct receipt handle, size the visibility timeout above your processing time, and write idempotent consumer logic regardless - standard queues are at-least-once by design.
Yes. There is essentially no downside: it reduces both empty responses and delivery latency compared to short polling.
In most cases yes. A single topic with per-subscription filter policies handles routing subsets of events far more flexibly than maintaining a topic per event type.
The most common cause is a missing queue policy. SNS needs explicit sqs:SendMessage permission on each subscribed queue; without it, Publish still succeeds but delivery to that queue never happens.
Most do. Batching, long polling, visibility tuning, dead-letter queues, and filtering all apply to FIFO resources too, with the added constraint that FIFO must pair with FIFO throughout (topic, queue, and DLQ).
Stack versions: This page was written for boto3 1.43.x (Python 3.10+) and the AWS SDK for JavaScript v3 (Node.js 18+).
Reviewed by Chris St. John·Last updated Jul 25, 2026