Messaging patterns comparison
Message Queue vs Pub/Sub
Two fundamental patterns for asynchronous communication between services. Getting this distinction right is the first step to designing a reliable event-driven architecture — and it comes up in virtually every microservices system design discussion.
TL;DR
- Message Queue — point-to-point. One producer, one consumer processes each message. Message is removed once acknowledged. Best for task distribution and work queues. Examples: RabbitMQ (default queue), SQS.
- Pub/Sub — broadcast. One publisher, many subscribers each receive a copy. Best for event notification and fan-out. Examples: Kafka topics, SNS, Google Pub/Sub.
- They complement each other. The SNS → SQS pattern (fan-out to isolated queues) is one of the most common patterns in AWS-based microservices.
Side-by-side comparison
| Aspect | Message Queue | Pub/Sub |
|---|---|---|
| Delivery model | Point-to-point: one consumer per message | Broadcast: all subscribers receive a copy |
| Ordering | Typically FIFO within a queue | Not guaranteed across subscribers |
| Persistence | Message waits until consumed (durable) | Varies — Redis drops, Kafka retains by offset |
| Fan-out | One message → one consumer | One message → all subscribers |
| Coupling | Producer knows there is a queue | Publisher knows nothing about subscribers |
| Load balancing | Natural — competing consumers share work | Each subscriber does all the work independently |
| Use case | Task queues, email sending, job workers | Event streaming, notifications, audit logs |
| Examples | RabbitMQ, Amazon SQS, Celery | Apache Kafka, Amazon SNS, Google Pub/Sub, Redis Pub/Sub |
Code side-by-side
Publishing an order event and consuming it:
Message Queue (SQS — one worker)
// Producer: send task to queue
await sqs.sendMessage({
QueueUrl: ORDER_QUEUE_URL,
MessageBody: JSON.stringify({
orderId: 'ord_123',
action: 'send_confirmation_email',
}),
}).promise();
// Consumer: exactly one worker picks this up
// Other workers get different messages Pub/Sub (SNS → multiple SQS queues)
// Publisher: broadcast event
await sns.publish({
TopicArn: ORDER_EVENTS_TOPIC,
Message: JSON.stringify({
orderId: 'ord_123',
event: 'order_placed',
}),
}).promise();
// SNS fans out to:
// → SQS queue for email service
// → SQS queue for fulfilment service
// → SQS queue for analytics When to use a Message Queue
- Task distribution. You have a pool of workers and want to share work evenly — image resizing, email sending, PDF generation.
- Exactly-once processing required. Each job must be done by exactly one worker; duplicate processing would cause errors (double charge, double send).
- Rate limiting downstream services. Queue depth acts as a natural buffer; consumers process at a sustainable rate even when producers burst.
- Retry with backoff. Failed messages go to a dead-letter queue for inspection and reprocessing without blocking healthy messages.
When to use Pub/Sub
- Event notification to multiple services. A user signs up → auth service, email service, analytics service, and onboarding service all need to know.
- Audit logging and observability. Every service publishes events; a central subscriber records them all without the publishers knowing.
- Decoupling producers from consumers. New subscribers can be added without changing the publisher — true open/closed principle at the architecture level.
- Event sourcing and stream processing. Kafka topics retain all events; consumers replay history to rebuild state or run analytics.
English phrases engineers use
Message Queue conversations
- "Messages pile up in the queue when consumers are slow."
- "Failed messages go to the dead-letter queue (DLQ)."
- "We have competing consumers — 5 workers share the same queue."
- "The consumer must acknowledge the message or it's requeued."
- "We set a visibility timeout to prevent duplicate processing."
Pub/Sub conversations
- "We publish an event to the topic; subscribers react independently."
- "The email service subscribes to the user-signup topic."
- "We do fan-out via SNS → multiple SQS queues."
- "Kafka consumers track their offset and can replay old events."
- "The publisher is decoupled — it doesn't know who's listening."
Quick decision tree
- One consumer should process each message → Message Queue
- Multiple independent services need the same event → Pub/Sub
- Task distribution among worker pool → Message Queue
- Audit log / event stream → Pub/Sub (Kafka)
- Need replay of past events → Pub/Sub (Kafka)
- Need dead-letter queue and retry → Message Queue (SQS/RabbitMQ)
- Need both broadcast AND isolated processing → SNS + SQS fan-out
Frequently asked questions
What is a message queue in plain English?
A message queue is a holding area for messages sent between services, with a point-to-point delivery model: one producer sends a message, and exactly one consumer processes it. Once consumed and acknowledged, the message is gone. Think of a task queue — one worker picks up each job. Examples: RabbitMQ, Amazon SQS.
What is the Pub/Sub pattern?
Publish/Subscribe (Pub/Sub) decouples producers (publishers) from consumers (subscribers) through topics. When a publisher sends a message to a topic, every subscriber to that topic receives a copy. One event, many receivers. Examples: Google Pub/Sub, Amazon SNS, Kafka topics, Redis Pub/Sub.
Can a message queue fan out to multiple consumers?
A single queue is point-to-point. To fan out with a queue-based system (like SQS), you combine it with a Pub/Sub layer — SNS broadcasts to multiple SQS queues, each with its own consumer. RabbitMQ achieves this with exchange types (fanout, topic).
Which preserves message ordering better?
Both can preserve ordering, but with constraints. SQS standard queues do not guarantee ordering; SQS FIFO queues and RabbitMQ single-queue setups do. Kafka preserves ordering within a partition. Pub/Sub systems with multiple subscribers and parallel delivery typically do not guarantee cross-subscriber ordering.
What happens if a consumer is down?
In a message queue, the message waits (up to a configurable retention period) until a consumer comes back up. This is the durability guarantee. In a basic Pub/Sub system (e.g., Redis Pub/Sub), messages sent while a subscriber is offline are lost. Kafka Pub/Sub is durable — subscribers catch up from their last offset.
When would I use both patterns together?
A common architecture: an order-placed event is published to a Pub/Sub topic (SNS), which fans out to multiple SQS queues — one for the email service, one for the fulfilment service, one for analytics. Each downstream service processes at its own pace via its dedicated queue.