Amazon SQS (Queues & Decoupling)
Key concepts
Standard vs FIFO queues
Visibility timeout
Dead letter queues
Long polling vs short polling
Message retention period
Overview
Amazon Simple Queue Service (SQS) is a fully managed message queuing service that enables you to decouple and scale microservices, distributed systems, and serverless applications. SQS eliminates the complexity of managing message-oriented middleware and allows you to send, store, and receive messages between software components at any volume.
Understanding SQS is critical for the SAA-C03 exam because it's a foundational service for building resilient, loosely coupled architectures. You must know the differences between Standard and FIFO queues, configure visibility timeouts and dead-letter queues properly, understand polling strategies, and design for decoupling and load leveling scenarios.
SQS Decoupling
SQS enables loose coupling by allowing producers to send messages without knowing who processes them and when. Messages persist in the queue until successfully processed, preventing data loss during consumer failures or traffic spikes.
Exam questions frequently test Standard vs FIFO queue selection, visibility timeout configuration, DLQ setup, and scaling EC2/Lambda consumers based on queue metrics. Know when ordering matters (FIFO) vs throughput (Standard).
Key Concepts
SQS Overview

Amazon SQS Basics
Amazon SQS is a pull-based messaging service where consumers poll the queue for messages. Key characteristics:
- Fully Managed: No infrastructure to manage
- Highly Available: Distributed across multiple AZs
- Scalable: Handles any message volume
- Secure: Encryption at rest and in transit
- Cost-Effective: Pay only for what you use
Standard vs FIFO Queues

Standard vs FIFO Queues
| Feature | Standard Queue | FIFO Queue |
|---|---|---|
| Throughput | Nearly unlimited | 300 TPS (3,000 with batching) |
| Ordering | Best-effort (may be out of order) | Strict first-in-first-out |
| Delivery | At-least-once (may have duplicates) | Exactly-once processing |
| Deduplication | None (handle in application) | 5-minute deduplication window |
| Use Case | High throughput, duplicate-tolerant | Order-sensitive, no duplicates |
| Naming | Any name | Must end with .fifo |
STANDARD QUEUE:
├── Delivery: At-least-once (duplicates possible)
├── Ordering: Best-effort (may be out of order)
├── Throughput: Nearly unlimited TPS
├── Deduplication: None built-in
└── Best For:
├── High-volume workloads
├── Duplicate-tolerant processing
├── Application logs
└── Background job processing
FIFO QUEUE:
├── Delivery: Exactly-once processing
├── Ordering: Strict FIFO (within message group)
├── Throughput: 300 TPS (3,000 with batching)
├── Deduplication: 5-minute window
└── Best For:
├── Financial transactions
├── Order processing (e-commerce)
├── Command sequences
└── Events requiring strict orderingMessage Groups (FIFO)
Message Groups
FIFO queues use Message Group IDs to ensure ordering within a group while allowing parallel processing across groups. Messages with the same group ID are processed in order, but different groups can be processed concurrently.
FIFO QUEUE WITH MESSAGE GROUPS:
Message Group: "user-123" Message Group: "user-456"
┌──────────────────────────┐ ┌──────────────────────────┐
│ Order 1 → Order 2 → 3 │ │ Order A → Order B → C │
│ (processed in sequence) │ │ (processed in sequence) │
└──────────────────────────┘ └──────────────────────────┘
│ │
└──────────┬─────────────────────────┘
│
▼
PARALLEL PROCESSING
(Different groups processed concurrently)
USE CASES:
├── Per-user: MessageGroupId = userId (user actions in order)
├── Per-order: MessageGroupId = orderId (order steps in order)
├── Per-device: MessageGroupId = deviceId (device events in order)
└── Single group: MessageGroupId = "all" (all messages in order)Queue Configuration
Visibility Timeout
Visibility Timeout
The visibility timeout determines how long a message is hidden from other consumers after being received. During this time, the consumer processes and deletes the message. If not deleted, the message becomes visible again for reprocessing.
VISIBILITY TIMEOUT FLOW:
Time 0s: Consumer A receives Message
└── Message becomes INVISIBLE
Time 0-30s: Consumer A processing...
└── Other consumers cannot see message
Time 30s (default timeout):
├── If deleted: Message removed permanently ✓
└── If NOT deleted: Message becomes VISIBLE again
└── Another consumer can receive it
CONFIGURATION:
├── Default: 30 seconds
├── Minimum: 0 seconds
├── Maximum: 12 hours
└── Can be extended programmatically (ChangeMessageVisibility)
BEST PRACTICE:
├── Set timeout > expected processing time
├── Add buffer for retries/errors
├── Extend timeout if processing takes longer
└── Rule of thumb: 6x average processing timeVisibility Timeout Scenarios
| Scenario | Visibility Timeout | Why |
|---|---|---|
| Quick processing (< 5s) | 30 seconds (default) | Fast retry if failure |
| Image processing (2 min) | 5-10 minutes | Allow completion + buffer |
| Video transcoding (30 min) | 1 hour | Long processing needs buffer |
| Batch processing | Extend dynamically | Unpredictable duration |
Message Retention
Message Retention
Message retention period determines how long messages stay in the queue if not processed. After this period, messages are automatically deleted regardless of whether they were processed.
MESSAGE RETENTION:
├── Default: 4 days
├── Minimum: 1 minute
├── Maximum: 14 days
IMPORTANT CONSIDERATIONS:
├── Messages deleted after retention period
├── Cannot be recovered once deleted
├── DLQ retention should be longer than source queue
└── Original timestamp preserved when moved to DLQ
SCENARIO (DLQ RETENTION):
Source Queue: 4 days retention
DLQ: 14 days retention
Day 0: Message sent to source queue
Day 3: Message moved to DLQ (after 3 failed attempts)
└── Message has 11 days left (14 - 3 = 11)
NOT 14 days from DLQ arrival!Delay Queues
Delay Queues
Delay queues let you postpone the delivery of new messages for a specified duration. Messages sent to delay queues remain invisible for the delay period before being available for processing.
DELAY QUEUE:
├── Default: 0 seconds (no delay)
├── Maximum: 15 minutes
├── Applies to: All new messages in queue
USE CASES:
├── Rate limiting API calls
├── Scheduling delayed processing
├── Building retry mechanisms
├── Coordinating timed workflows
MESSAGE-LEVEL DELAY (Standard Queue only):
├── Override queue-level delay per message
├── Use DelaySeconds parameter when sending
├── Not supported in FIFO queues
└── Range: 0 to 15 minutesDead Letter Queues (DLQ)

Dead Letter Queues
A Dead Letter Queue (DLQ) captures messages that cannot be processed successfully after a specified number of attempts. DLQs help isolate problematic messages for debugging without blocking the main queue.
DEAD LETTER QUEUE SETUP:
Source Queue ──────► Consumer
│ │
│ Process
│ │
│ ┌───────┴───────┐
│ │ │
│ Success Failure
│ │ │
│ Delete Return
│ Message to Queue
│ │
│ Retry...
│ │
│ (after maxReceiveCount)
│ │
└──────────► Dead Letter Queue
REDRIVE POLICY (Source Queue):
{
"deadLetterTargetArn": "arn:aws:sqs:region:account:my-dlq",
"maxReceiveCount": 3
}
KEY SETTINGS:
├── maxReceiveCount: Times message received before DLQ (1-1000)
├── DLQ must be same type (Standard → Standard, FIFO → FIFO)
├── DLQ retention > Source retention (best practice)
└── Redrive allow policy: Controls which queues can use DLQDLQ Redrive
DLQ Redrive
DLQ redrive allows you to move messages from the DLQ back to the source queue (or another queue) for reprocessing after fixing the underlying issue.
DLQ REDRIVE WORKFLOW:
1. IDENTIFY: Messages appear in DLQ
└── Set CloudWatch alarm on ApproximateNumberOfMessagesVisible
2. INVESTIGATE: Analyze failed messages
├── Check message content
├── Review consumer logs
└── Identify root cause
3. FIX: Resolve the underlying issue
├── Fix consumer code
├── Update dependencies
└── Correct configuration
4. REDRIVE: Move messages back
├── AWS Console: Start message redrive
├── CLI: aws sqs start-message-move-task
└── Messages return to source queue
REDRIVE ALLOW POLICY (on DLQ):
{
"redrivePermission": "byQueue",
"sourceQueueArns": [
"arn:aws:sqs:region:account:source-queue"
]
}Polling Strategies
Short Polling vs Long Polling
| Feature | Short Polling | Long Polling |
|---|---|---|
| Wait Time | Returns immediately | Waits up to 20 seconds |
| Empty Responses | Many (if queue empty) | Fewer |
| Cost | Higher (more API calls) | Lower |
| Latency | Higher (many requests) | Lower (fewer requests) |
| Configuration | WaitTimeSeconds = 0 | WaitTimeSeconds = 1-20 |
Long Polling
Long polling reduces costs and improves efficiency by allowing the consumer to wait for messages instead of returning immediately. The consumer waits up to 20 seconds for a message before returning empty.
SHORT POLLING (Default):
├── ReceiveMessageWaitTimeSeconds = 0
├── Returns immediately (even if empty)
├── Queries subset of SQS servers
├── May return empty even when messages exist
└── Higher cost (more API calls)
LONG POLLING (Recommended):
├── ReceiveMessageWaitTimeSeconds = 1-20
├── Waits for messages to arrive
├── Queries ALL SQS servers
├── Reduces empty responses
└── Lower cost, better efficiency
CONFIGURATION OPTIONS:
1. Queue-level: Set ReceiveMessageWaitTimeSeconds
2. Request-level: Use WaitTimeSeconds parameter
BEST PRACTICE:
├── Use long polling (20 seconds recommended)
├── Set at queue level for consistency
├── Reduces costs significantly
└── Note: Single-threaded apps polling multiple queues
may need short pollingLambda Integration
SQS with Lambda
Lambda can be configured as an event source for SQS, automatically polling the queue and invoking your function when messages arrive. Lambda manages scaling, batching, and error handling.
LAMBDA + SQS INTEGRATION:
Event Source Mapping
SQS Queue ─────────────────────────────────► Lambda Function
│ │
│ Polls queue │
│ Batches messages │
│ Invokes function │
│ Manages scaling │
└────────────────────────────────────┘
SCALING BEHAVIOR (Standard Queue):
├── Starts with 5 concurrent batches
├── Scales up to 300 more per minute
├── Maximum: 1,250 concurrent invocations
├── Scales down when traffic decreases
└── Minimum: 2 concurrent invocations
CONFIGURATION OPTIONS:
├── Batch Size: 1-10,000 messages (default: 10)
├── Batch Window: 0-300 seconds (wait for full batch)
├── Maximum Concurrency: Limit concurrent invocations
├── Report Batch Item Failures: Return partial failures
└── Function Error Handling: DLQ on function level
FIFO QUEUE WITH LAMBDA:
├── Maintains message order within group
├── One concurrent invocation per message group
├── Multiple groups = parallel processing
└── Scales based on number of message groupsBatch Processing
{
"EventSourceArn": "arn:aws:sqs:region:account:my-queue",
"FunctionName": "my-function",
"BatchSize": 100,
"MaximumBatchingWindowInSeconds": 30,
"ScalingConfig": {
"MaximumConcurrency": 50
},
"FunctionResponseTypes": ["ReportBatchItemFailures"]
}BATCH ITEM FAILURE REPORTING:
Scenario: Batch of 10 messages, 2 fail
WITHOUT ReportBatchItemFailures:
├── Entire batch retried
├── 8 successful messages reprocessed
├── Duplicates in downstream systems
└── Inefficient, wastes compute
WITH ReportBatchItemFailures:
├── Return failed message IDs
├── Only failed messages retried
├── Successful messages deleted
└── Efficient, no duplicates
LAMBDA RESPONSE FORMAT:
{
"batchItemFailures": [
{ "itemIdentifier": "message-id-1" },
{ "itemIdentifier": "message-id-2" }
]
}Auto Scaling with SQS
EC2 Auto Scaling with SQS
EC2 Auto Scaling groups can scale based on SQS queue depth using the ApproximateNumberOfMessages metric. This enables dynamic scaling to handle varying workloads efficiently.
AUTO SCALING ARCHITECTURE:
SQS Queue ──► CloudWatch Metric ──► Auto Scaling Policy ──► EC2 Instances
│
ApproximateNumberOfMessagesVisible
│
▼
Target: Messages per instance
SCALING METRICS:
├── ApproximateNumberOfMessagesVisible: Messages available
├── ApproximateNumberOfMessagesNotVisible: In-flight messages
├── ApproximateAgeOfOldestMessage: Queue backlog age
└── NumberOfMessagesReceived: Incoming rate
CUSTOM METRIC FORMULA:
Backlog per Instance = ApproximateNumberOfMessagesVisible
─────────────────────────────────────
Running Capacity (instances)
Target Value = Acceptable backlog per instance
SCALING POLICY EXAMPLE:
├── Metric: ApproximateNumberOfMessagesVisible
├── Target: 100 messages per instance
├── Scale Out: When > 100 messages/instance
├── Scale In: When < 50 messages/instance
└── Cooldown: 300 secondsSecurity
Encryption
ENCRYPTION AT REST:
├── SSE-SQS: AWS managed key (default, no cost)
├── SSE-KMS: Customer managed KMS key
│ ├── More control over key rotation
│ ├── Audit via CloudTrail
│ └── Cross-account access possible
└── Enable at queue creation or modify later
ENCRYPTION IN TRANSIT:
├── HTTPS endpoints enforced
├── TLS 1.2+ required
└── VPC endpoints available (PrivateLink)
ACCESS POLICY EXAMPLE (KMS):
{
"Effect": "Allow",
"Principal": {"AWS": "arn:aws:iam::account:role/consumer"},
"Action": [
"kms:Decrypt",
"kms:GenerateDataKey"
],
"Resource": "*"
}Access Control
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "sns.amazonaws.com"
},
"Action": "sqs:SendMessage",
"Resource": "arn:aws:sqs:region:account:my-queue",
"Condition": {
"ArnEquals": {
"aws:SourceArn": "arn:aws:sns:region:account:my-topic"
}
}
}
]
}Best Practices
- Use Long Polling: Set ReceiveMessageWaitTimeSeconds to 20 seconds to reduce costs
- Configure DLQs: Always set up dead-letter queues for production workloads
- Design Idempotent Consumers: Handle duplicate messages gracefully (Standard queues)
- Set Appropriate Visibility Timeout: Match to processing time plus buffer
- Use Message Groups Wisely: Maximize parallelism in FIFO queues
- Monitor Queue Metrics: Set alarms on queue depth, DLQ count, and message age
- Use Batch Operations: Reduce API calls with batch send/receive/delete
- Consider FIFO Only When Needed: Standard queues offer higher throughput
Common Exam Scenarios
Exam Scenarios
| Scenario | Solution | Why |
|---|---|---|
| Decouple web tier from processing | SQS Standard between tiers | Buffering, independent scaling |
| Process orders in sequence | SQS FIFO queue | Strict ordering required |
| Handle processing failures | Configure DLQ | Isolate failed messages |
| Reduce polling costs | Enable long polling (20s) | Fewer API calls |
| Scale workers to demand | Auto Scaling on queue depth | Dynamic capacity |
| Prevent duplicate processing | FIFO queue or idempotent design | Exactly-once or handle duplicates |
| Messages stuck in queue | Increase visibility timeout | Processing takes longer than timeout |
| Lambda batch partial failure | ReportBatchItemFailures | Retry only failed messages |
Common Pitfalls
Pitfall 1: Visibility Timeout Too Short
Mistake: Setting visibility timeout shorter than processing time.
Why it fails: Messages reappear before processing completes; processed multiple times.
Correct Approach: Set timeout to at least 6x average processing time; extend programmatically if needed.
Pitfall 2: No Dead Letter Queue
Mistake: Not configuring a DLQ for production queues.
Why it fails: Poison messages block queue forever; no visibility into failures.
Correct Approach: Always configure DLQ; set alarms on DLQ message count.
Pitfall 3: Using FIFO When Not Needed
Mistake: Choosing FIFO queue when ordering isn't required.
Why it fails: FIFO has 300 TPS limit vs unlimited for Standard; unnecessary constraint.
Correct Approach: Use Standard unless ordering is required; design idempotent consumers.
Pitfall 4: Short Polling in Production
Mistake: Using default short polling (WaitTimeSeconds = 0).
Why it fails: Many empty responses; higher costs; unnecessary API calls.
Correct Approach: Enable long polling (20 seconds) at queue level.
Pitfall 5: DLQ Retention Shorter Than Source
Mistake: Setting DLQ retention period shorter than source queue.
Why it fails: Messages may be deleted from DLQ before you can investigate.
Correct Approach: DLQ retention should be longer (e.g., source: 4 days, DLQ: 14 days).
Related Services
Quick Reference
SQS Limits
SQS Limits
| Parameter | Standard | FIFO |
|---|---|---|
| Throughput | Unlimited | 300 TPS (3K batched) |
| Message Size | 256 KB | 256 KB |
| Retention | 1 min - 14 days | 1 min - 14 days |
| Visibility Timeout | 0s - 12 hours | 0s - 12 hours |
| Delay | 0 - 15 minutes | 0 - 15 minutes |
| Long Poll Wait | 0 - 20 seconds | 0 - 20 seconds |
| Batch Size | 1 - 10 | 1 - 10 |
| In-Flight Messages | 120,000 | 20,000 |
Message Attributes
{
"MessageBody": "Your message content here",
"MessageAttributes": {
"OrderType": {
"DataType": "String",
"StringValue": "Premium"
},
"Priority": {
"DataType": "Number",
"StringValue": "1"
}
},
"MessageDeduplicationId": "unique-id-123",
"MessageGroupId": "order-group-456"
}Test Your Knowledge
A company processes financial transactions that must be handled in the exact order received. They expect 200 transactions per second. Which SQS queue type should they use?
An application processes messages from SQS, but some messages keep reappearing after being processed. What is the most likely cause?
A Lambda function processes batches of 100 messages from SQS. Occasionally, 2-3 messages in a batch fail while the rest succeed. How should the function handle this efficiently?
A company wants to reduce SQS costs. Currently, consumers poll the queue every second and often receive empty responses. What should they implement?