Home CS Fundamentals Message Queues: Kafka, RabbitMQ, and SQS Patterns Explained
Intermediate 3 min · July 13, 2026

Message Queues: Kafka, RabbitMQ, and SQS Patterns Explained

Learn message queue patterns with Kafka, RabbitMQ, and SQS.

N
Naren Founder & Principal Engineer

20+ years shipping production systems from the metal up. Written from production experience, not tutorials.

Follow
Production
production tested
July 13, 2026
last updated
2,165
articles · all by Naren
Before you start⏱ 15-20 min read
  • Basic understanding of distributed systems
  • Familiarity with command line
  • AWS account for SQS examples (optional)
 ● Production Incident 🔎 Debug Guide ⚙ Triage Commands
Quick Answer
  • Message queues decouple producers and consumers, enabling async communication.
  • Kafka is best for high-throughput event streaming; RabbitMQ for reliable routing; SQS for fully managed cloud queues.
  • Common patterns: point-to-point, publish-subscribe, work queues, and request-reply.
  • Production pitfalls include message loss, ordering issues, and backpressure.
  • Debugging involves checking consumer lag, dead-letter queues, and monitoring throughput.
✦ Definition~90s read
What is Message Queues?

A message queue is a communication mechanism that allows asynchronous message passing between distributed components, decoupling producers and consumers.

Imagine a restaurant kitchen.
Plain-English First

Imagine a restaurant kitchen. Orders (messages) come in, and chefs (consumers) pick them up. A message queue is like the order rack. Kafka is a conveyor belt that keeps all orders forever; RabbitMQ is a smart rack that routes orders to specific stations; SQS is a cloud-based rack that scales automatically. If the kitchen gets busy, orders pile up but don't get lost.

In modern distributed systems, services need to communicate reliably without blocking each other. Message queues solve this by acting as a buffer between producers (senders) and consumers (receivers). They enable asynchronous processing, load leveling, and fault tolerance. Whether you're building a microservices architecture, processing real-time data streams, or handling background jobs, understanding message queue patterns is essential.

Three major players dominate the landscape: Apache Kafka, RabbitMQ, and Amazon SQS. Each has strengths and trade-offs. Kafka excels at high-throughput event streaming and replayability. RabbitMQ offers flexible routing and reliable delivery. SQS provides a fully managed, infinitely scalable queue in the cloud.

In this tutorial, you'll learn the core patterns—point-to-point, publish-subscribe, work queues, and request-reply—and how to implement them with each technology. We'll also cover real-world production incidents, debugging techniques, and common mistakes to avoid. By the end, you'll be equipped to choose the right queue and pattern for your use case.

What is a Message Queue?

A message queue is a communication mechanism that allows asynchronous message passing between distributed components. Producers send messages to a queue, and consumers retrieve them. This decouples the sender and receiver, enabling independent scaling and fault tolerance.

Key concepts
  • Producer: Creates and sends messages.
  • Consumer: Receives and processes messages.
  • Broker: The server that hosts queues and routes messages.
  • Queue/Topic: The channel where messages are stored.
  • Message: The data payload, often with headers and metadata.

Message queues provide at-least-once, at-most-once, or exactly-once delivery semantics. They also support ordering guarantees within a partition or queue.

Common use cases
  • Task queues (e.g., image processing)
  • Event streaming (e.g., user activity tracking)
  • Log aggregation
  • Microservices communication
basic-producer-consumer.shBASH
1
2
3
4
5
6
7
8
9
10
# Simulate a simple queue using netcat (for illustration only)
# Producer: echo "message" | nc -l -p 9999 &
# Consumer: nc localhost 9999

# In practice, use Kafka, RabbitMQ, or SQS
# Example: Kafka producer from command line
echo "order:123" | kafka-console-producer --broker-list localhost:9092 --topic orders

# Kafka consumer
kafka-console-consumer --bootstrap-server localhost:9092 --topic orders --from-beginning
Output
order:123
🔥Why Not HTTP?
📊 Production Insight
Always set a message TTL and dead-letter queue to handle expired or failed messages.
🎯 Key Takeaway
Message queues enable asynchronous, decoupled communication with delivery guarantees.

Core Message Queue Patterns

  1. Point-to-Point (Work Queue): A message is consumed by exactly one consumer. Used for task distribution.
  2. Publish-Subscribe: A message is broadcast to all subscribed consumers. Used for event notifications.
  3. Request-Reply: A producer sends a request and waits for a reply, often using a temporary queue.
  4. Routing: Messages are routed based on routing keys or headers (e.g., RabbitMQ exchanges).

Each pattern solves different problems. Point-to-point ensures load balancing; pub-sub enables fan-out; request-reply simulates RPC; routing allows selective consumption.

In Kafka, pub-sub is achieved via consumer groups (each group gets all messages). In RabbitMQ, exchanges and bindings implement routing. SQS supports point-to-point and can emulate pub-sub via SNS.

rabbitmq-work-queue.shBASH
1
2
3
4
5
6
7
8
9
# RabbitMQ work queue using rabbitmqadmin
# Declare a queue
rabbitmqadmin declare queue name=task_queue durable=true

# Publish a message
rabbitmqadmin publish exchange=amq.default routing_key=task_queue payload='{"task": "process_image"}'

# Consume (in a loop)
rabbitmqadmin get queue=task_queue ackmode=ack_requeue_false
Output
{"task": "process_image"}
💡Pattern Selection
📊 Production Insight
In pub-sub, ensure consumers are idempotent to handle duplicate messages.
🎯 Key Takeaway
Choose the pattern that matches your delivery semantics: one consumer, all consumers, or selective routing.

Kafka: High-Throughput Event Streaming

Apache Kafka is a distributed event streaming platform designed for high throughput, durability, and replayability. It stores messages in topics partitioned across brokers. Each message has an offset, and consumers track their position.

Key features
  • Partitions: Allow parallel consumption within a consumer group.
  • Retention: Messages persist for a configurable time, enabling replay.
  • Exactly-once semantics: Supported via idempotent producers and transactions.
  • Consumer groups: Each group gets a copy of all messages (pub-sub).

Kafka is ideal for log aggregation, metrics, and event sourcing. It's not ideal for low-latency request-reply or complex routing.

Example: A food delivery service uses Kafka to stream order events. Each order is a message in the 'orders' topic. The payment service, inventory service, and notification service each have their own consumer group.

kafka-producer-consumer.shBASH
1
2
3
4
5
6
7
8
9
10
# Create a topic with 3 partitions
kafka-topics --bootstrap-server localhost:9092 --create --topic orders --partitions 3 --replication-factor 1

# Produce messages with keys for ordering
kafka-console-producer --bootstrap-server localhost:9092 --topic orders --property parse.key=true --property key.separator=:
>order1:{"id":1}
>order2:{"id":2}

# Consume from a consumer group
kafka-console-consumer --bootstrap-server localhost:9092 --topic orders --group payment-group --property print.key=true
Output
order1 {"id":1}
order2 {"id":2}
⚠ Ordering Guarantees
📊 Production Insight
Monitor consumer lag with kafka-consumer-groups. Lag indicates processing bottlenecks.
🎯 Key Takeaway
Kafka is best for high-throughput, durable event streaming with replay capability.

RabbitMQ: Flexible Routing and Reliability

RabbitMQ is a message broker that supports multiple messaging protocols (AMQP, MQTT, STOMP). It excels at routing messages through exchanges and bindings.

Key concepts
  • Exchange: Receives messages from producers and routes them to queues based on routing keys.
  • Queue: Stores messages until consumed.
  • Binding: Links an exchange to a queue with a routing pattern.
  • Acknowledgments: Consumers can acknowledge messages to ensure delivery.
Exchange types
  • Direct: Routes by exact routing key.
  • Topic: Routes by pattern matching (e.g., 'order.*').
  • Fanout: Broadcasts to all bound queues.
  • Headers: Routes based on header attributes.

RabbitMQ is ideal for complex routing, request-reply, and tasks requiring immediate acknowledgment. It's not as high-throughput as Kafka but offers more flexibility.

rabbitmq-topic-exchange.shBASH
1
2
3
4
5
6
7
8
9
10
11
12
# Declare a topic exchange
rabbitmqadmin declare exchange name=orders type=topic durable=true

# Bind queues with patterns
rabbitmqadmin declare queue name=payment_queue durable=true
rabbitmqadmin declare binding source=orders destination=payment_queue routing_key=order.paid

rabbitmqadmin declare queue name=shipping_queue durable=true
rabbitmqadmin declare binding source=orders destination=shipping_queue routing_key=order.*

# Publish a message
rabbitmqadmin publish exchange=orders routing_key=order.paid payload='{"order_id": 123}'
Output
Message published
🔥Dead Letter Exchanges
📊 Production Insight
Use manual acknowledgments to avoid losing messages. Set prefetch count to control consumer load.
🎯 Key Takeaway
RabbitMQ provides flexible routing with exchanges, making it suitable for complex workflows.

Amazon SQS: Fully Managed Cloud Queue

Amazon Simple Queue Service (SQS) is a fully managed message queue service that scales automatically. It offers two types: Standard (high throughput, at-least-once) and FIFO (exactly-once, ordered).

Key features
  • No broker management: AWS handles scaling and durability.
  • Visibility timeout: After a consumer receives a message, it becomes invisible to others for a configurable period.
  • Dead-letter queues: Configure a DLQ for failed messages.
  • Long polling: Reduces empty responses by waiting for messages.

SQS is ideal for decoupling microservices in AWS, handling background jobs, and buffering requests. It's less flexible than RabbitMQ and lacks pub-sub natively (use SNS for fan-out).

Example: An e-commerce site uses SQS to queue order processing tasks. The order service sends a message, and the inventory service polls the queue.

sqs-send-receive.shBASH
1
2
3
4
5
6
7
8
# Send a message to SQS queue
aws sqs send-message --queue-url https://sqs.us-east-1.amazonaws.com/123456789012/MyQueue --message-body '{"order_id": 456}'

# Receive messages
aws sqs receive-message --queue-url https://sqs.us-east-1.amazonaws.com/123456789012/MyQueue --wait-time-seconds 10

# Delete message after processing
aws sqs delete-message --queue-url https://sqs.us-east-1.amazonaws.com/123456789012/MyQueue --receipt-handle <ReceiptHandle>
Output
{"Messages": [{"MessageId": "...", "ReceiptHandle": "...", "Body": "{\"order_id\": 456}"}]}
💡FIFO vs Standard
📊 Production Insight
Always set a dead-letter queue and monitor the number of messages in DLQ to catch processing failures.
🎯 Key Takeaway
SQS is the easiest to set up and scales automatically, but offers less control than Kafka or RabbitMQ.

Choosing the Right Queue

  • Throughput: Kafka handles millions of messages per second; RabbitMQ tens of thousands; SQS unlimited with Standard.
  • Routing: RabbitMQ offers the most flexible routing; Kafka uses topic partitioning; SQS is simple.
  • Durability: All three persist messages, but Kafka's log-based storage allows replay.
  • Latency: RabbitMQ and SQS have lower latency for small messages; Kafka optimizes for batch throughput.
  • Managed vs Self-hosted: SQS is fully managed; Kafka and RabbitMQ can be self-hosted or managed (Confluent, AWS MSK, etc.).
  • Ordering: Kafka per partition, SQS FIFO, RabbitMQ per queue.

Consider your team's expertise and operational overhead. For startups, SQS is often the simplest. For large-scale event streaming, Kafka is the standard. For complex routing, RabbitMQ shines.

comparison.shBASH
1
2
3
4
5
6
# No code needed, but here's a quick test to measure throughput
# Kafka: produce 1M messages
time kafka-producer-perf-test --topic test --num-records 1000000 --record-size 100 --throughput -1 --producer-props bootstrap.servers=localhost:9092

# RabbitMQ: use perf-test plugin
rabbitmq-perf-test --queue test --producers 1 --consumers 1 --size 100 --rate 10000
Output
Kafka: 500000 msg/s
RabbitMQ: 10000 msg/s
🔥Hybrid Approach
📊 Production Insight
Benchmark with realistic workloads, not just synthetic tests.
🎯 Key Takeaway
Match the queue to your throughput, routing, and operational needs.
● Production incidentPOST-MORTEMseverity: high

The Case of the Missing Orders: A Kafka Consumer Lag Disaster

Symptom
Users reported orders not being processed, and the system showed increasing consumer lag.
Assumption
The developer assumed the consumer was slow due to database writes and increased batch size.
Root cause
The consumer was polling too frequently with a small max.poll.records, causing rebalances and wasted time.
Fix
Increased max.poll.records, adjusted fetch.max.bytes, and added monitoring for lag.
Key lesson
  • Monitor consumer lag as a primary metric.
  • Tune poll parameters to match processing speed.
  • Use dead-letter queues for failed messages.
  • Implement backpressure mechanisms.
  • Test consumer behavior under load.
Production debug guideSymptom to Action5 entries
Symptom · 01
Messages not being consumed
Fix
Check consumer group status, lag, and if consumer is running.
Symptom · 02
High latency in message delivery
Fix
Monitor network, broker load, and consumer processing time.
Symptom · 03
Duplicate messages
Fix
Enable idempotent producers and deduplication in consumers.
Symptom · 04
Message loss
Fix
Check retention settings, enable persistence, and use acknowledgments.
Symptom · 05
Out-of-order messages
Fix
Use single partition or key-based partitioning for ordering.
★ Quick Debug Cheat SheetImmediate actions for common message queue issues.
Consumer lag growing
Immediate action
Increase consumers or optimize processing.
Commands
kafka-consumer-groups --bootstrap-server localhost:9092 --group my-group --describe
Check lag per partition
Fix now
Scale out consumers or reduce batch size.
Messages stuck in queue+
Immediate action
Check dead-letter queue and consumer errors.
Commands
rabbitmqctl list_queues name messages_ready messages_unacknowledged
Check consumer logs
Fix now
Restart consumer or move messages to DLQ.
High latency+
Immediate action
Monitor broker CPU and network.
Commands
kafka-topics --bootstrap-server localhost:9092 --describe --topic my-topic
Check partition count
Fix now
Increase partitions or optimize producer batching.
FeatureKafkaRabbitMQSQS
ThroughputVery high (millions/s)High (tens of thousands/s)High (unlimited with Standard)
RoutingTopic partitioningExchanges (direct, topic, fanout, headers)Simple queue (no routing)
Delivery GuaranteesAt-least-once, exactly-onceAt-least-once, at-most-onceAt-least-once (Standard), exactly-once (FIFO)
OrderingPer partitionPer queueFIFO queues only
ManagementSelf-hosted or managedSelf-hosted or managedFully managed
LatencyLow (batch), higher for single messagesVery lowLow
⚙ Quick Reference
6 commands from this guide
FileCommand / CodePurpose
basic-producer-consumer.shecho "order:123" | kafka-console-producer --broker-list localhost:9092 --topic o...What is a Message Queue?
rabbitmq-work-queue.shrabbitmqadmin declare queue name=task_queue durable=trueCore Message Queue Patterns
kafka-producer-consumer.shkafka-topics --bootstrap-server localhost:9092 --create --topic orders --partiti...Kafka
rabbitmq-topic-exchange.shrabbitmqadmin declare exchange name=orders type=topic durable=trueRabbitMQ
sqs-send-receive.shaws sqs send-message --queue-url https://sqs.us-east-1.amazonaws.com/12345678901...Amazon SQS
comparison.shtime kafka-producer-perf-test --topic test --num-records 1000000 --record-size 1...Choosing the Right Queue

Key takeaways

1
Message queues decouple producers and consumers, enabling async, resilient systems.
2
Kafka is for high-throughput event streaming; RabbitMQ for flexible routing; SQS for simplicity.
3
Always monitor consumer lag and use dead-letter queues.
4
Choose the right pattern
point-to-point, pub-sub, request-reply, or routing.

Common mistakes to avoid

4 patterns
×

Not setting a dead-letter queue

×

Ignoring consumer lag

×

Assuming messages are always ordered

×

Using too many partitions

INTERVIEW PREP · PRACTICE MODE

Interview Questions on This Topic

Q01JUNIOR
Explain the difference between at-least-once and at-most-once delivery.
Q02SENIOR
How does Kafka achieve high throughput?
Q03SENIOR
Design a system for real-time order processing using message queues.
Q01 of 03JUNIOR

Explain the difference between at-least-once and at-most-once delivery.

ANSWER
At-least-once ensures every message is delivered at least once, but may cause duplicates. At-most-once delivers at most once, but messages may be lost. Exactly-once is the ideal but harder to achieve.
FAQ · 5 QUESTIONS

Frequently Asked Questions

01
What is the difference between Kafka and RabbitMQ?
02
Can I use SQS for pub-sub?
03
How do I ensure exactly-once delivery?
04
What is consumer lag?
05
Should I use a message queue or a database?
N
Naren Founder & Principal Engineer

20+ years shipping production systems from the metal up. Written from production experience, not tutorials.

Follow
Verified
production tested
July 13, 2026
last updated
2,165
articles · all by Naren
🔥

That's Computer Networks. Mark it forged?

3 min read · try the examples if you haven't

Previous
gRPC Architecture and Protocol
28 / 30 · Computer Networks
Next
NAT: Network Address Translation Types and Traversal