Skip to content
Low Level Design Mastery Logo
LowLevelDesign Mastery

Message Queues Fundamentals

Decoupling systems with asynchronous messaging

Synchronous systems: Service A calls Service B and waits for response.

Diagram

Problems:

  • Service A blocks waiting for B
  • If B is slow, A is slow
  • If B crashes, A fails
  • Tight coupling

Solution: Message Queues - Asynchronous, decoupled communication!


A message queue is a buffer that stores messages between senders (producers) and receivers (consumers). It acts as an intermediary component that enables asynchronous, decoupled communication between services or components in a distributed system.

At its essence, a message queue is a temporary storage mechanism that decouples the production of messages from their consumption. Instead of a producer directly calling a consumer and waiting for a response, the producer sends a message to the queue and continues with other work. The consumer retrieves messages from the queue when it’s ready to process them, completely independently of when the messages were produced.

This decoupling provides several critical benefits: temporal decoupling (producer and consumer don’t need to be active at the same time), spatial decoupling (they don’t need to know each other’s location), and synchronization decoupling (they don’t need to wait for each other).

Diagram
  1. Decoupling - Services don’t know about each other
  2. Asynchronous - Non-blocking communication
  3. Reliability - Messages persisted, can retry
  4. Scalability - Multiple consumers, load distribution
  5. Resilience - If consumer fails, messages stay in queue

One producer, one or more consumers. Each message processed once.

Diagram

Characteristics:

  • Load balancing - Multiple consumers share work
  • Task distribution - Work distributed across consumers
  • Scalability - Add more consumers to scale
  • Each message processed once - One consumer gets each message

Use cases:

  • Background job processing
  • Email sending
  • Image processing
  • Data transformation
  • Task queues

One publisher, multiple subscribers. Each subscriber gets copy of message.

Diagram

Characteristics:

  • Fan-out - One message → multiple consumers
  • Decoupling - Publisher doesn’t know subscribers
  • Event broadcasting - Notify multiple services
  • Each subscriber gets copy - Independent processing

Use cases:

  • Event notifications
  • Real-time updates
  • Cache invalidation
  • Log aggregation
  • Analytics events

Message may be lost, but never duplicated.

Diagram

Characteristics:

  • Simple
  • Low latency
  • May lose messages
  • No retry

Use when: Non-critical messages, metrics, logs

Message delivered at least once, may have duplicates.

Diagram

Characteristics:

  • Reliable (won’t lose messages)
  • Retries on failure
  • May have duplicates
  • Consumer must be idempotent

Use when: Critical messages, order processing, payments

Message delivered exactly once. Requires deduplication.

Diagram

Characteristics:

  • No duplicates
  • No lost messages
  • Complex implementation
  • Performance overhead

Use when: Financial transactions, critical operations


Ordering ensures messages processed in sequence.

Example: User account balance updates

Message 1: Balance = 100
Message 2: Balance = 150 (add 50)
Message 3: Balance = 120 (subtract 30)

Correct order: 100 → 150 → 120
Wrong order: 100 → 120 → 150 = 150 (wrong!)

1. Per-Partition Ordering (Kafka)

  • Messages in same partition processed in order
  • Different partitions can process in parallel

2. Per-Queue Ordering (RabbitMQ)

  • Single consumer per queue
  • Messages processed sequentially

3. Global Ordering

  • All messages processed in order
  • Slower (no parallelism)

  • Decoupling needed - Services shouldn’t know about each other
  • Async processing - Don’t want to wait for response
  • Load leveling - Smooth out traffic spikes
  • Reliability - Need guaranteed delivery
  • Scalability - Need to scale consumers independently
  • Synchronous operations - Need immediate response
  • Simple request-response - Overhead not worth it
  • Ordering not needed - Can use simpler patterns
  • Low latency critical - Queues add latency

LLD Connection: Implementing Message Handlers

Section titled “LLD Connection: Implementing Message Handlers”

At the code level, message queues translate to producer/consumer classes, message handlers, and acknowledgment logic.


Producer-Consumer

One producer, multiple consumers. Each message processed once. Perfect for task distribution.

Pub-Sub

One publisher, multiple subscribers. Each gets copy. Perfect for event broadcasting.

Delivery Guarantees

At-least-once most common. Requires idempotent consumers. Exactly-once is hardest but most reliable.

Ordering Matters

Message ordering critical for state changes. Per-partition ordering balances order and parallelism.