Updated Nov 5, 20266 min read

What Is Amazon SQS? Queues, Visibility Timeouts and Dead-Letter Queues

Amazon SQS is a managed message queue on AWS. How standard and FIFO queues differ, how visibility timeouts and long polling work, what dead-letter queues catch, how pricing is shaped, and how to get SNS and SQS from application code.

Amazon Simple Queue Service (SQS) is AWS's managed message queue: producers put messages on a queue, consumers pull them, process them and delete them. SQS handles durability, scaling and the locking that keeps two consumers from working the same message at once. You do not run brokers or partitions.

Most of the complexity sits around the queue rather than in the send and receive calls: visibility timeouts, long polling, dead-letter queues, standard versus FIFO, and the IAM and Terraform that surround every environment. This guide covers those pieces and how Encore (infrastructure from code) provisions SNS and SQS from Pub/Sub declared in code.

Amazon SQS at a glance

What SQS doesWhat stays with you
HostingFully managed queue, no brokersChoosing standard or FIFO
DeliveryAt least once (standard); exactly-once processing within a window (FIFO)Idempotent consumers
OrderingBest-effort (standard); per message group (FIFO)Picking a message group ID
Hiding in-flight workVisibility timeout (default 30 seconds)Matching timeout to handler duration
FailuresRedrive to a dead-letter queueSetting maxReceiveCount, alarming, redriving
Size and retentionUp to 1 MiB per message; retain 1 minute to 14 days (default 4 days)Payload design, retention choice
Fan-outOne consumer group per queueSNS in front when several consumers need the same event
SecurityServer-side encryption, queue policiesIAM principals and KMS keys

How SQS works

A producer calls SendMessage (or a batch of up to 10). The message is stored redundantly across SQS servers. A consumer calls ReceiveMessage, gets up to 10 messages, and while it works those messages stay in the queue but are invisible for the visibility timeout. After success the consumer calls DeleteMessage with the receipt handle. If it crashes or exceeds the timeout, the message becomes visible again and another consumer can receive it. Messages that sit longer than the retention period are deleted automatically.

Long polling sets WaitTimeSeconds up to 20 on receive (or as a queue default). The call waits for a message instead of returning empty immediately, which cuts empty responses and request cost. Short polling returns at once and may sample only a subset of SQS servers.

Messages can be up to 1 MiB. Larger payloads usually go to S3 with a pointer in the message body, often via the SQS Extended Client libraries. The SQS developer guide covers the full lifecycle.

Standard vs FIFO queues

Standard queues are the default. Throughput scales with little planning, delivery is at least once, and ordering is best-effort. Occasional duplicates mean every consumer should be idempotent.

FIFO queues (names ending in .fifo) preserve the order of messages that share a MessageGroupId and deduplicate within a five-minute window using MessageDeduplicationId or content-based deduplication. Throughput is capped per partition unless you turn on high-throughput mode. Use FIFO when order for an entity (an account, an order) matters; otherwise prefer standard queues.

SQS alone does not fan out one event to many independent consumers. The usual pattern is an SNS topic with one SQS queue subscribed per consumer.

Visibility timeouts and dead-letter queues

Pick a visibility timeout above your slowest successful handler. Too short and a second consumer starts the same work. Too long and failures wait that long before retry. You can change visibility per message with ChangeMessageVisibility, including setting it to 0 to make a message available immediately. The maximum visibility timeout is 12 hours from first receive.

A dead-letter queue is a second queue attached with a redrive policy. After maxReceiveCount receives without a delete, SQS moves the message there. Set the DLQ retention longer than the source queue's. Alarm on DLQ depth, inspect the bodies, fix the consumer, then redrive. Avoid a DLQ on a FIFO queue when strict order across the whole stream must never break.

Pricing shape

SQS charges per API request with no minimum fee. The free tier includes 1 million requests per month. Each 64 KiB chunk of payload counts as one request, so a 1 MiB send bills as 16 requests. A single API call can carry up to 10 messages. FIFO actions that send, receive, delete or change visibility bill at FIFO rates. Cross-region and internet data transfer follow standard AWS data transfer pricing. There are no servers to keep warm, and an idle queue with no requests costs nothing.

How Encore provisions SNS and SQS

Encore

Encore combines an open source infrastructure SDK for TypeScript and Go with a platform that provisions and deploys into your own AWS or GCP account. You declare a topic and subscriptions in code, and on AWS Encore creates an SNS topic with an SQS queue and dead-letter queue per subscription, as listed in the AWS infrastructure docs. On GCP the same declarations become GCP Pub/Sub with dead-letter topics.

The Infrastructure page in the Encore dashboard with a database's configuration panel open, showing fields for vCPUs, memory, storage, availability type, max connections and backups.
Each provisioned resource can be reviewed and its configuration edited per environment in the Encore dashboard. The screenshot shows a GCP Cloud SQL database.

Set up the app

Get started
brew install encoredev/tap/encore &&
encore app create
Copy

Run in your terminal to get started locally.

~
$ encore app create shop --example=go/hello-world$ cd shop && mkdir order receipt

A Go service publishes; another subscribes with retries that feed the dead-letter queue:

// order/order.go package order import ( "context" "encore.dev/pubsub" ) type OrderPlaced struct { OrderID int64 `json:"order_id"` Email string `json:"email"` } var OrderPlacedTopic = pubsub.NewTopic[*OrderPlaced]("order-placed", pubsub.TopicConfig{ DeliveryGuarantee: pubsub.AtLeastOnce, }) type PlaceParams struct { Email string `json:"email"` } //encore:api public method=POST path=/orders func Place(ctx context.Context, p *PlaceParams) error { _, err := OrderPlacedTopic.Publish(ctx, &OrderPlaced{OrderID: 42, Email: p.Email}) return err }
// receipt/receipt.go package receipt import ( "context" "time" "encore.app/order" "encore.dev/pubsub" "encore.dev/rlog" ) var _ = pubsub.NewSubscription(order.OrderPlacedTopic, "send-receipt", pubsub.SubscriptionConfig[*order.OrderPlaced]{ Handler: SendReceipt, RetryPolicy: &pubsub.RetryPolicy{ MinBackoff: 1 * time.Second, MaxRetries: 5, }, }, ) func SendReceipt(ctx context.Context, e *order.OrderPlaced) error { rlog.Info("sending receipt", "order_id", e.OrderID) return nil }

encore run runs both services with an in-memory Pub/Sub, and the local development dashboard traces each message. A handler that returns an error is retried, and after MaxRetries the message goes to the subscription's dead-letter queue, as covered in the Go Pub/Sub docs. The same model exists in TypeScript. Encore provisions an IAM role for the service, so no queue URLs or access keys sit in config. Connecting AWS is covered in deploying to your own cloud.

Encore Pub/Sub is a queue and fan-out system. It does not keep history for replay the way a log such as Kafka does. When an AI coding agent adds a consumer, it writes one more NewSubscription and tests it locally, and the SQS queue and dead-letter queue arrive with the deploy.

Best fit: Go and TypeScript teams who need queues and fan-out between services on AWS or GCP with retries and dead-letter queues, declared next to the code that publishes and consumes.

Good to know

  • Standard SQS cannot rebuild a read model from past events once messages are deleted. Keep an event table or use a log if you need replay.
  • Plan IAM per producer and consumer; a shared wildcard policy is how queues get over-shared across environments.
  • Test DLQ redrive in a non-production account before you need it during an incident.

Frequently asked questions

What is Amazon SQS used for?

Amazon SQS is a fully managed message queue on AWS. Producers send messages, consumers receive and delete them after processing, and SQS buffers work so services stay decoupled. Typical uses are sending email after signup, processing uploads, and fanning work out to background workers.

What is the difference between standard and FIFO SQS queues?

Standard queues deliver at least once with best-effort ordering and nearly unlimited throughput. FIFO queues preserve order within a message group ID, support exactly-once processing within a deduplication window, and have lower throughput limits unless high-throughput mode is enabled.

What is an SQS visibility timeout?

The period after a consumer receives a message during which that message is hidden from other consumers. The default is 30 seconds and the maximum is 12 hours. If the consumer does not delete the message before the timeout, it becomes visible again and is retried.

How do I create an SQS-backed queue between Go services without managing SQS directly?

With Encore, declare a topic with pubsub.NewTopic and a handler with pubsub.NewSubscription, then publish with Publish. Messages are delivered locally during development, and on AWS Encore provisions SNS and SQS with a dead-letter queue for the subscription.

Deploy to your cloud on AWS and Google Cloud
without managing infrastructure

Encore lets developers and agents define application infrastructure directly in code, then automatically provisions it from local development to production in your AWS or GCP account.

~/orders — claude
Claude Code
Claude Code v2.1.180Opus 5.5~/orders