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

AspectMessage QueuePub/Sub
Delivery modelPoint-to-point: one consumer per messageBroadcast: all subscribers receive a copy
OrderingTypically FIFO within a queueNot guaranteed across subscribers
PersistenceMessage waits until consumed (durable)Varies — Redis drops, Kafka retains by offset
Fan-outOne message → one consumerOne message → all subscribers
CouplingProducer knows there is a queuePublisher knows nothing about subscribers
Load balancingNatural — competing consumers share workEach subscriber does all the work independently
Use caseTask queues, email sending, job workersEvent streaming, notifications, audit logs
ExamplesRabbitMQ, Amazon SQS, CeleryApache 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).