*Message Queues

September 15, 2025

Why queues?

  • Temporal decoupling, retries, backpressure, ordering control.

Delivery semantics

  • At‑least‑once (default): requires idempotent consumers.
  • At‑most‑once: no retries → risk of loss.
  • Exactly‑once: expensive; emulate via idempotence + transactions.

Tools

Kafka (distributed log), RabbitMQ (AMQP), SQS/Pub/Sub (cloud).

Best practices

  • DLQ, metrics (lag, throughput), compaction (Kafka), balanced partitions.

Code: Producer/Consumer (Kafka, Node.js)

// language-javascript
import { Kafka } from 'kafkajs'
const kafka = new Kafka({ clientId: 'app', brokers: ['kafka:9092'] })

// Producer with idempotent key
const producer = kafka.producer()
await producer.connect()
await producer.send({
  topic: 'events',
  messages: [{ key: orderId, value: JSON.stringify(event) }],
})

// Consumer with at-least-once, idempotent handler
const consumer = kafka.consumer({ groupId: 'events-group' })
await consumer.connect()
await consumer.subscribe({ topic: 'events', fromBeginning: false })
await consumer.run({
  eachMessage: async ({ message }) => {
    const id = message.key.toString()
    if (!(await redis.setnx(`evt:${id}`, 1))) return // dedupe
    await handle(JSON.parse(message.value.toString()))
  },
})

Exactly-once discussion

  • True exactly-once is extremely hard in distributed systems. Aim for at-least-once with idempotent consumers, or transactional outbox + consumer offsets in the same DB transaction where possible.

Backpressure and redrive

# language-nginx
location /ingest {
  limit_req zone=ingest burst=100 nodelay;
  proxy_pass http://ingestor;
}
# language-bash
# Redrive failed messages from DLQ to main topic after fix
aws sqs receive-message --queue-url "$DLQ" | jq -r '.Messages[].ReceiptHandle' | while read h; do
  aws sqs send-message --queue-url "$MAIN" --message-body @payload.json
  aws sqs delete-message --queue-url "$DLQ" --receipt-handle "$h"
done

Ordering and partitioning

  • If ordering matters per key, choose partition key carefully (e.g., userId) and keep consumer group size aligned with partitions.