DEV Community

Cover image for Message Queues (SQS)
Gouranga Das Samrat
Gouranga Das Samrat

Posted on

Message Queues (SQS)

One-liner: A message queue decouples services by letting a producer drop messages into a queue, where consumers pick them up asynchronously β€” neither needs to be available at the same time.


πŸ“Œ The Problem: Tight Coupling

User places order β†’
  [Order Service] β†’ calls [Payment Service] β†’ waits β†’
                  β†’ calls [Email Service] β†’ waits β†’
                  β†’ calls [Inventory Service] β†’ waits β†’
  All done! (3s total, 3 failure points)
Enter fullscreen mode Exit fullscreen mode

Problems:

  • High latency β€” user waits for every downstream service
  • Cascading failure β€” if Email service is down, order fails
  • Tight coupling β€” Order service knows about all downstream services
  • No retry logic β€” failures are permanent

πŸ’‘ The Solution: Message Queue

User places order β†’ [Order Service] β†’ DROP message in queue β†’ RESPOND (fast!)
                                              ↓
                                   [Queue]
                                   /    |    \
                          [Payment] [Email] [Inventory]  ← process at their own pace
Enter fullscreen mode Exit fullscreen mode

Benefits:

  • Decoupling β€” services don't know about each other
  • Resilience β€” downstream service can be down; message waits in queue
  • Load leveling β€” queue absorbs traffic spikes
  • Retry β€” failed processing retried automatically

πŸ”„ Queue Concepts

Producer & Consumer

[Producer] β†’ push message β†’ [Queue] β†’ pull message β†’ [Consumer]
Enter fullscreen mode Exit fullscreen mode
  • Producer: Creates and sends messages
  • Consumer: Reads and processes messages
  • Queue: Durable buffer between them

Message Lifecycle

1. Producer sends message β†’ Queue stores it
2. Consumer polls queue β†’ Queue marks message as "in-flight" (invisible to others)
3. Consumer processes β†’ Success: Consumer deletes message
                     β†’ Failure: After visibility timeout, message reappears
Enter fullscreen mode Exit fullscreen mode

Visibility Timeout

Consumer pulls message β†’ message hidden for 30 seconds
If consumer crashes β†’ 30 seconds later, message reappears β†’ another consumer picks it up
If consumer succeeds β†’ consumer deletes message β†’ gone forever
Enter fullscreen mode Exit fullscreen mode

☁️ AWS SQS (Simple Queue Service)

Standard Queue

  • Unlimited throughput
  • At-least-once delivery β€” message may be delivered more than once!
  • Best-effort ordering β€” no strict FIFO

FIFO Queue

  • Exactly-once processing β€” deduplication
  • Strict ordering β€” first in, first out
  • Limited throughput β€” 300 msg/sec (or 3000 with batching)

SQS Key Concepts

Message retention:  Up to 14 days (default: 4 days)
Visibility timeout: How long consumer has to process (default: 30s)
Dead Letter Queue:  Where failed messages go after N retries
Max message size:   256 KB
Enter fullscreen mode Exit fullscreen mode

SQS + Lambda (Serverless Consumer)

[SQS Queue] ──triggers──► [Lambda Function]
                           (auto-scales to process backlog)
Enter fullscreen mode Exit fullscreen mode

πŸ”€ Queue Patterns

Work Queue (Task Distribution)

[Producer] β†’ [Queue] β†’ [Worker 1]
                     β†’ [Worker 2]
                     β†’ [Worker 3]

Each message processed by exactly ONE worker
Enter fullscreen mode Exit fullscreen mode

Use case: Image resizing, email sending, PDF generation

Fan-out via Multiple Queues

[Event] β†’ [SNS Topic] β†’ [Queue A] β†’ [Consumer A]
                      β†’ [Queue B] β†’ [Consumer B]
                      β†’ [Queue C] β†’ [Consumer C]
Enter fullscreen mode Exit fullscreen mode

Each consumer gets a copy of the message. (See: SNS/Pub-Sub)

Priority Queue

High priority queue β†’ processed first by consumers
Low priority queue  β†’ processed when high is empty
Enter fullscreen mode Exit fullscreen mode

♻️ Dead Letter Queue (DLQ)

When a message fails to process after N retries β†’ move to DLQ:

[Queue] β†’ [Consumer fails 3 times] β†’ [DLQ]
                                          ↑
                                    Ops team inspects,
                                    fixes bug, redrives
Enter fullscreen mode Exit fullscreen mode
// SQS Redrive Policy
{
  "deadLetterTargetArn": "arn:aws:sqs:us-east-1:123:my-dlq",
  "maxReceiveCount": 3 // after 3 failures, move to DLQ
}
Enter fullscreen mode Exit fullscreen mode

⚠️ Idempotency β€” Critical Requirement

Standard queues deliver at-least-once. Your consumer MUST be idempotent:

Message: "charge user 42 for $99"

❌ Non-idempotent: Just run the charge every time β†’ user charged twice!
βœ… Idempotent: Check if orderId already processed β†’ skip if yes
Enter fullscreen mode Exit fullscreen mode
async function processPayment(message) {
  const { orderId, userId, amount } = message;

  // Check idempotency key
  const alreadyProcessed = await redis.get(`payment:${orderId}`);
  if (alreadyProcessed) return; // skip duplicate

  await chargeUser(userId, amount);
  await redis.setex(`payment:${orderId}`, 86400, "1"); // mark done
}
Enter fullscreen mode Exit fullscreen mode

πŸ“Š SQS vs Other Queues

Feature AWS SQS RabbitMQ Apache Kafka
Type Managed cloud Self-hosted broker Distributed log
Retention 14 days Until consumed Configurable (forever)
Ordering Best-effort/FIFO Per-queue Per-partition
Replay ❌ ❌ βœ… (replay from offset)
Throughput Very high High Very high
Use case Decoupling tasks Complex routing Event streaming

🎨 Diagram

The diagram shows:

  • Producer β†’ Queue β†’ Multiple consumers
  • Visibility timeout flow (in-flight β†’ reappear)
  • Dead Letter Queue after max retries
  • Fan-out via SNS β†’ multiple queues

πŸ”‘ Key Takeaways

  • Queues decouple services and absorb traffic spikes
  • Visibility timeout ensures messages aren't lost if a consumer crashes
  • Always implement idempotent consumers with SQS Standard
  • DLQ is essential for debugging failed messages
  • Use FIFO when order matters; Standard when throughput matters

Top comments (0)