Skip to main content

📨 Message Queues

A post office sorting room

The Post Office Analogy

Sending a letter:

  • You drop letter at post office
  • Post office holds it
  • Recipient picks it up when ready
  • You don't wait for them to read it!

Message queues are digital post offices. Services send messages and move on. Receivers process when ready.


What Is a Message Queue?

Middleware that stores and forwards messages.

Producer → Queue → Consumer

Producer sends message.
Queue holds message.
Consumer processes when ready.

Decoupled, asynchronous communication.

Before Queues

Service A calls Service B directly:

A: "Process this order"
B: (processing... takes some time...)
A: (waiting... waiting...)
B: "Done"
A: (finally continues)

Synchronous. A is blocked.

With Queues

A → Queue → B

A: "Here's an order" (sends to queue, moves on)
A: (continues doing other work)
B: (picks up message when ready)
B: (processes at its own pace)

Asynchronous. A is free.

When to Use

Async Processing

User uploads image.
Resize needed (slow!).

Without queue:
  User waits... waits... waits...

With queue:
  "Image queued for processing"
  User continues.
  Processing happens in background.

Decoupling Services

Order service needs:
  - Inventory update
  - Email notification
  - Analytics tracking

Direct calls: Order service knows all three.
Queue: Order publishes "OrderPlaced". Others listen.

Handling Spikes

1000 requests/second spike!

Without queue: Services overwhelmed.
With queue: Messages buffered, processed at steady rate.

Core Concepts

Producer

Sends messages to queue.
"I have work for someone."

Consumer

Receives messages from queue.
Processes the work.

Queue

Holds messages.
FIFO usually (first in, first out).
Persisted until consumed.

Message

The data being sent.
Usually JSON, but can be any format.

{
  "type": "order",
  "orderId": "123",
  "userId": "456"
}

Message Patterns

Point-to-Point

One producer, one consumer.
Message delivered to exactly one consumer.

Producer → Queue → Consumer

Work distribution, task processing.

Publish-Subscribe

One producer, many consumers.
All subscribers get the message.

Producer → Topic → Consumer 1
                → Consumer 2
                → Consumer 3

Events, notifications, broadcasting.

Work Queue

Multiple producers, multiple consumers.
Messages distributed among consumers.

Producer 1 ─┐
Producer 2 ─┼──→ Queue ──→ Consumer 1
Producer 3 ─┘          ──→ Consumer 2

Scale processing by adding consumers.

Delivery Guarantees

At-Most-Once

Message delivered 0 or 1 times.
May be lost if consumer fails.
Fastest.
Use when: Logging, metrics (loss acceptable)

At-Least-Once

Message delivered 1 or more times.
Typically not lost, but duplicates are possible.
Consumer must handle duplicates.
Use when: Most applications

Exactly-Once

Message delivered exactly 1 time.
Complex to implement.
Performance overhead.
Use when: Financial transactions

Acknowledgments

How does queue know message was processed?

1. Consumer receives message
2. Consumer processes message
3. Consumer sends ACK (acknowledgment)
4. Queue removes message

No ACK? Message redelivered.

If consumer dies before ACK:
  Message goes to another consumer.
  Message can be retried.

Dead Letter Queue

Messages that can't be processed.

Failed 3 times?
→ Move to dead letter queue.
→ Investigate later.
→ Doesn't block main queue.

Handle edge cases gracefully.

ToolTypeBest For
RabbitMQTraditional brokerFlexible routing
Apache KafkaStreaming platformHigh volume, durability
AWS SQSCloud queueSimple, serverless
RedisIn-memorySimple, fast
NATSLightweightCloud native

When to Choose

RabbitMQ:
  Complex routing, traditional messaging

Kafka:
  High volume, event streaming, replay needed

SQS:
  AWS environment, simplicity, serverless

Redis:
  Speed priority, simple queuing

Common Patterns

Retry with Backoff

Processing fails.
Wait a bit, retry.
Fails again? Wait longer.
Increase the delay over time.

Exponential backoff prevents hammering.

Priority Queues

VIP orders processed first.
Emergency alerts skip the line.

Priority levels determine order.

Message TTL

Message older than a chosen window?
Discard it.

Time-sensitive data doesn't wait forever.

Common Mistakes

1. Not Handling Duplicates

At-least-once means duplicates possible.
Consumer must be idempotent!

Process order → Check if already processed.

2. No Dead Letter Queue

Bad message blocks queue.
Processing stuck forever.

In many systems, setting up a DLQ (or equivalent) is a good idea.

3. Too Large Messages

Very large messages → Slow, memory issues.

Better: Store data elsewhere, send reference.
"Process file at s3://bucket/file.jpg"

4. Ignoring Order

Messages may arrive out of order.
If order matters, use partitioning or sequence numbers.

FAQ

Q: Message queue vs REST API?

REST: Synchronous, immediate response needed. Queue: Asynchronous, work can be deferred.

Q: How do I scale consumers?

Run more consumer instances. Queue distributes messages.

Q: What about message ordering?

Per-partition ordering (Kafka). Or single consumer per queue.

Q: Can I replay messages?

Kafka: Yes, retains messages. RabbitMQ: No, once consumed.


Summary

Message queues enable asynchronous communication between services, buffering messages until consumers are ready.

Key Takeaways:

  • Producer → Queue → Consumer
  • Decoupled, asynchronous
  • Delivery guarantees: at-most/least/exactly once
  • ACKs ensure reliable processing
  • Dead letter queue for failures
  • Tools: RabbitMQ, Kafka, SQS

Message queues are the postal service of microservices!

Leave a Comment

Comments (0)

Be the first to comment on this concept.

Comments are approved automatically.