SQS is a fully managed message queue. Producers send messages to a queue; consumers poll for messages and process them. Messages are stored redundantly across multiple AZs.
Standard vs FIFO
Feature
Standard Queue
FIFO Queue
Throughput
Unlimited
300 msg/s (batch: 3000/s)
Ordering
At-least-once, no guarantee
Exactly-once, strict order
Duplicates
May be delivered multiple times
Deduplicated (5-min window)
Price
$0.40/million requests
$0.50/million requests
Use case
High throughput, can tolerate duplicates
Financial transactions, strict order
Core Concepts
Producer Consumer
│ │
├──► Message 1 ──────────────────►│ (Delete after processing)
├──► Message 2 ──────────────────►│
├──► Message 3 ──────────────────►│
│ │
└──► Dead Letter Queue (after maxReceiveCount)
Time ──────────────────────────────────────────────────────►
t=0 Message delivered to Consumer A
Visibility timeout = 30 seconds
│
│ If Consumer A crashes at t=25s (before delete):
│ Message becomes visible again at t=30s
│ Another consumer can pick it up
│
t=30 Message visible again (if not deleted)
Visibility timeout resets (30 more seconds)
│
t=60 Message visible again (if not deleted)
... up to maxReceiveCount, then DLQ
Lambda Integration (Event Source Mapping)
# SQS trigger Lambda (event source mapping)import jsondef handler(event, context): for record in event['Records']: body = json.loads(record['body']) print(f"Processing message: {body}") # Lambda automatically deletes the message after successful execution # If Lambda throws an error, the message becomes visible again
Scenario 1: An e-commerce checkout processing 1M orders/month. Each order triggers 1 SQS message. 1M requests × 0.40/million=0.40/month. Plus Lambda invocations (~0.20/month).Total:0.60/month for message queuing.
Scenario 2: A high-throughput image processing pipeline with 50M messages/day. 50M/day × 30 = 1.5B/month. Using batch operations (10 messages/batch), that’s 150M API calls. 0.40×150=60/month. Switching to FIFO with batching: 0.50×150=75/month.
Nuggets & Gotchas
SQS does NOT delete messages after ReceiveMessage — you MUST call DeleteMessage yourself: The message stays invisible for the VisibilityTimeout period, then reappears if not deleted. For Lambda, the SDK handles this automatically. For manual polling, you MUST call delete_message after successful processing.
SQS long polling (WaitTimeSeconds > 0) can delay empty responses up to that wait time: If you call receive_message with WaitTimeSeconds=20 and the queue is empty, the call blocks for up to 20 seconds. Design your consumer loops accordingly.
SQS message size is 256KB hard limit — for larger payloads, store in S3 and send S3 reference: Use the SQS extended client library which automatically stores large payloads in S3 and sends the reference in SQS.
SQS FIFO ordering is per message group ID — messages with different group IDs can be delivered out of order: If you need global ordering, use a single group ID. For partial ordering (per customer), use customer ID as group ID.
SQS visibility timeout doesn’t pause while your consumer is idle — it counts down from the moment the message is received: If your VisibilityTimeout is 30s and you spend 25s on processing before calling delete, you only have 5s left. Set it to 2-3x your expected processing time.