skip to content

In a message broker, what's the practical difference between publishing to a queue versus publishing to a topic, in terms of how many consumers receive each message?

level: middleimportance: must knowfreq 80%

answer

  1. queue = one consumer per message
  2. topic = every subscriber gets a copy
  3. competing consumers pattern
  4. fan-out-to-queue hybrid
  5. Kafka consumer groups = queue+topic hybrid

basics

~20 s

A queue delivers each message to exactly one consumer, like a shared to-do list where each task is picked up once. A topic broadcasts each message to every subscriber, like a radio station everyone tuned in hears.

solid answer

~40 s

A queue implements point-to-point messaging: each message is delivered to and consumed by exactly one consumer, even if multiple consumers are competing on the same queue (the competing consumers pattern) - used for work distribution. A topic implements publish/subscribe: each message is delivered to every subscriber that has registered interest, independently, so N subscribers each get their own copy - used for broadcasting events. Some brokers unify the two: Kafka topics are partitioned logs where each partition behaves queue-like within a consumer group (one member gets each message) but pub/sub-like across groups (every group gets its own copy of the whole topic).

go deeper

for a junior

Can state that a queue is one-message-one-consumer and a topic is one-message-many-consumers, with a simple example of each.

for a middle

Understands competing consumers for load balancing and can pick the right primitive for a described scenario.

for a senior

Knows the fan-out-to-queue hybrid pattern and can diagnose the 'wrong primitive' failure modes (starved subscribers or duplicated work).

for a principal

Can reason across broker products (RabbitMQ's exchange/queue model vs Kafka's partition/consumer-group model) and choose the right abstraction for a system's fan-out and parallelism needs.

## The two shapes A **queue** is a single ordered buffer of messages with one logical set of consumers competing for work. When multiple consumer processes attach to the same queue, the broker hands each message to only one of them — the **'competing consumers'** pattern, used to parallelize work across a pool of workers. Once a message is consumed and acknowledged, it's gone from the queue for everyone. A **topic**, by contrast, is a publish/subscribe channel: every consumer that subscribes gets its own independent copy of every message published after it subscribed. Internally, most topic implementations achieve this either by maintaining one delivery queue per subscriber, or — in log-based brokers — by having each subscriber track its own read offset into a shared, retained log, so multiple readers can independently lag or replay without affecting each other. ## Why both models exist These two models exist because they answer different questions. | Model | The question it answers | The primitive | |---|---|---| | Queues | 'how do I distribute a stream of work across a pool of workers so nobody idles and nobody duplicates work?' | a load-balancing primitive | | Topics | 'how do I notify every interested party that something happened, without the publisher needing to know who they are?' | a fan-out primitive | An order-placed event might need to reach an email service, an inventory service, and an analytics pipeline — three independent consumers doing unrelated work off the same event; that's a topic. Resizing ten thousand uploaded images is one unit of work that should be picked up once by whichever worker is free; that's a queue. ## What each gives up - **Queues** give natural load balancing and back-pressure, but make it hard for two different services to independently receive the same events without a fan-out layer in front. - **Topics** give decoupled, add-a-subscriber-anytime broadcast, but if you also want load-balanced parallel processing within one subscriber's own logic, you need multiple worker threads pulling from that subscriber's local buffer, or a hybrid model with consumer groups and partitions. A widely used pattern is **fan-out-to-queue**: a topic broadcasts to several queues (one per downstream system), and each queue then supports competing consumers within that system — getting both broadcast and parallel processing at once (e.g., Amazon SNS fanning out to multiple SQS queues). ## Failure modes - **The classic mistake** is putting competing consumers on what should be a topic: only one service ends up receiving each event and the others silently starve, with no error — just missing downstream data that's easy to miss until someone notices numbers don't add up. - **The inverse mistake** is fanning a work queue out as if it were pub/sub: every worker processes every task redundantly, causing duplicate side effects (e.g., charging a card three times). - **Head-of-line blocking.** Another queue failure mode is a poison message at the front of a strict FIFO queue, which can block everything behind it unless the broker supports skipping to a dead-letter destination. - **Outside the retention window.** For topics, a subscriber offline too long can fall outside the retention window and permanently miss messages, silently, unless it notices a gap in sequence numbers. ## How two products spell it - **RabbitMQ** makes the distinction explicit: you declare a queue, and separately declare an exchange (the routing layer) that can fan out to one or many queues; a 'fanout exchange' bound to three queues gives topic-like broadcast, while consumers attached to any single queue compete for its messages. - **Kafka** instead exposes one abstraction — the partitioned topic — and gets queue-like semantics via consumer groups: each partition is delivered to exactly one consumer per group (queue-style), while every distinct consumer group reads the entire topic independently (topic-style). Recognizing which model a given broker product uses is essential before designing a multi-consumer system on top of it.

  • If you need both broadcast to multiple services AND load-balanced parallel processing within one of those services, what pattern do you use?
    Fan-out-to-queue: publish to a topic/exchange that broadcasts to one queue per downstream service, then let each service run multiple competing consumers against its own queue. This is the standard pattern, e.g. SNS fanning out to several SQS queues.
  • How does Kafka let one topic behave like both a queue and a topic at the same time?
    Each partition is delivered to only one consumer within a given consumer group, giving queue-like work distribution across the group's members. But every separate consumer group reads the full topic independently from its own offset, giving topic-like broadcast across groups.
  • What silently breaks if a team mistakenly points three independent services at competing-consumer queues off the same work, instead of giving each its own queue?
    Only one of the three services will receive any given message - the other two starve with no visible error, since the broker considers the message delivered once any one competing consumer acknowledges it. This typically surfaces later as missing data that's confusing to debug.

A queue is like a single ticket counter with one line - each customer gets served by exactly one teller who steps up next. A topic is like a stadium announcement - everyone in the stands hears the same announcement independently, no one uses it up for anyone else.

saying these in an interview costs you the question

  • thinks 'topic' and 'queue' are just naming synonyms for the same behavior
  • assumes adding a second consumer to a queue broadcasts the message to both
  • doesn't know the fan-out-to-queue hybrid pattern
  • can't explain what a Kafka consumer group does
  • assumes topics are always slower or faster than queues without justification

context