In this article
Before you start
This page is one step of the distributed systems interview path.
Why interviewers ask this
Queues and events appear in most backend design rounds, because the moment two services talk through a broker, the failure modes change. A call that fails is visible; a message that is delivered twice, or out of order, or never, is not.
A weak answer says "put a queue in between to scale" and stops. A strong answer says what the queue promises (delivery at least once), what that costs (duplicates, so idempotent consumers), what it does not promise (global order), and what happens to a message that keeps failing. A Staff-level answer also separates a queue, where a consumed message disappears, from a log, where it stays and can be replayed, and picks one for the workload. The same ideas come up in a payment system design and in the backend interview questions round.
Message queues from first principles
- Message queue
- A message queue is a broker, a service that sits between programs, that stores messages from a producer until a consumer processes them, so the producer does not wait for the consumer and bursts of traffic are absorbed.
- Event-driven architecture
- Event-driven architecture is a design in which services announce facts that already happened, called events, and other services react to them without the sender knowing who is listening.
- Idempotent consumer
- An idempotent consumer is a message handler that gives the same final result whether it processes a message once or several times, usually by recording a message key and skipping keys it has already applied.
- Dead-letter queue
- A dead-letter queue is a separate queue that receives messages which failed processing too many times, so one bad message stops blocking the main queue and someone can inspect it.
In plain words
Think of a restaurant kitchen with an order rail. Waiters clip tickets to the rail and cooks take them when free. A waiter never waits for a particular cook, and a rush only makes the rail longer. The analogy breaks in one place: a kitchen ticket is thrown away once the dish is cooked, while some brokers keep every ticket in a ledger so a new cook can read the whole evening.
A producer is the program that sends a message. A consumer is the program that receives and handles it. The difference between a command and an event is the direction of the sentence. A command says "charge this card" and expects one receiver to act. An event says "an order was placed" and any number of receivers may react, or none.
In one precise sentence, a broker decouples the producer from the consumer in time and in rate, and the price is that you now reason about delivery, order and failure yourself.
Step 1: A queue decouples the producer from the consumer
The producer writes a message to the queue and moves on. The consumer pulls messages at its own pace. If the consumer is down for a while, messages wait; if traffic spikes, the queue grows instead of the consumer falling over.
In a classic queue the message is withheld from other consumers while one consumer works on it, and removed when that consumer confirms it is done. Amazon's documentation says a received message stays in the Amazon Simple Queue Service (SQS) queue but is temporarily not offered to other consumers; the consumer then deletes it. The confirmation is the key step: the broker only forgets a message when told the work succeeded.
Input: a message from a producer. Output: a message held until one consumer confirms it. You now know the basic contract, and the next step shows how it breaks.
Step 2: At-least-once delivery means duplicates
At-least-once delivery means a broker may hand a consumer the same message more than once but never loses it. The Confluent delivery documentation names three modes: at least once, at most once (a failure may lose a message) and exactly once (once and only once). The same page warns that many systems claim exactly once without meaning what you expect.
The order of two actions picks the mode. If a consumer processes a message and then saves its position, a crash in between means the message is processed a second time: at least once. If it saves the position first and then processes, a crash loses the message: at most once.
Queues repeat messages through the visibility timeout. The visibility timeout is the period a received message is withheld from other consumers; the SQS default is 30 seconds (Amazon SQS documentation). It is a lease, not a lock: the handler has not yet deleted the message, so if it is still working when the lease ends, another consumer receives it. An illustrative 45-second handler is therefore running twice from second 30.1
The fix is the idempotent consumer: give messages a primary key (a unique identifier for a record) so updates apply once, as the worked example below shows.
Step 3: A log keeps events and lets consumers replay
A log is an append-only record that keeps events after they are read. Confluent describes a Kafka topic as an ordered log of events stored durably, and says events are not deleted after they are consumed. Topics can be set to expire data by age or by size; that limit is called retention.
An offset is a consumer group's position in one partition's log; a consumer can reset it to an older value and reprocess the past (Confluent). That is replay, and a classic queue cannot do it because the message is gone after deletion. Partition logs are explained in Step 4.
Because the log is not consumed destructively, different consumer groups can each read every message (Kafka 101 course). One group can update a search index while another feeds analytics, and neither affects the other. For safety the log is copied to other machines; a common production setting is a replication factor of 3 (Confluent). This is the event-driven shape: the producer publishes a fact once and does not know who reads it.
Step 4: Partitions and consumer groups set order and parallelism
A partition is one ordered slice of a topic. Kafka writes events with the same key, such as a customer identifier, to the same partition, and a consumer of a partition reads its events in the order they were written (Confluent). Order therefore holds inside a partition, not across the whole topic, and "Kafka keeps global order" is wrong.
A consumer group is a set of consumers that share the work of a topic. Kafka assigns each partition to one consumer in the group, so no two consumers in a group read the same partition; with three partitions and three consumers, each consumer handles one (Kafka 101 course). Adding or losing a consumer triggers a rebalance, a reassignment of partitions among the group's consumers.
It follows that in a classic consumer group, extra consumers beyond the partition count sit idle. Choosing a key that spreads load evenly while keeping related events together is the core design decision.
Step 5: A dead-letter queue parks messages that keep failing
A poison message is one that fails every time it is processed, for example because its content is malformed. Without a limit it is redelivered forever and wastes consumer time. Amazon describes the fix: a limit called maxReceiveCount, and when a message's ReceiveCount exceeds it, SQS is designed to move the message to a dead-letter queue. The source queue, the dead-letter queue and the limit together are called a redrive policy. The SQS documentation recommends configuring one.
A dead-letter queue does not fix anything. It parks the bad messages so the main flow continues; a person or a job must inspect them, repair the cause and send them back. In an interview, say you alert on the dead-letter queue's depth.
Step-by-step description
- The queue holds messages between producer and consumer.
- A slow consumer loses its lease and the queue redelivers.
- A separate log keeps events and consumers track an offset.
- Order holds per partition; a group splits partitions.
- Messages that keep failing are parked for inspection.
- A consumer that is slower than the visibility timeout gets its message delivered again.
- Ordering in Kafka is kept per partition, not per topic.
- A dead-letter queue parks a message after too many failed receives.
The figure repeats the facts of the steps. A consumer that is slower than the visibility timeout gets its message delivered again. Ordering in Kafka is kept per partition, not per topic. A dead-letter queue parks a message after too many failed receives.
Knowing it is half the job. Saying it is the other half.
Interview Clozo is an AI interview copilot for real interview rounds: it hears the question and puts a strong answer on your screen, and you say it in your own words. See the features or how it works.
Start Free Trial →Worked example
Every number in this section is illustrative input to a short script, and every result is computed by it.1
A handler needs 45 seconds. The queue uses the 30-second default timeout (Amazon). The message reappears at second 30, a second consumer starts it, and for 15 seconds two copies run. The second copy finishes at second 75. Setting the timeout to 54 seconds, the handler time plus a 20% margin, removes the overlap.1
Take a dead-letter limit of 3 receives with that same 30-second timeout and a message that always fails. It is received at seconds 0, 30 and 60, and the fourth receive at about second 90 would exceed the limit, so the message moves to the dead-letter queue.1
Now the offset order. A consumer handles 10 messages and saves its position after every 5. If it saves after processing and crashes after message 8, it restarts at message 6, so 3 messages are processed twice. If it saves before processing and crashes after message 8, messages 9 and 10 are lost, which is 2 messages.1
For idempotence, take two payment events of 25 and 10 units, and a duplicate of the first. A naive handler totals 60. A handler that records event keys totals 35.1
Last, lag. A topic receives 6,000 messages per second over 6 partitions, which is 1,000 per partition. A consumer handles 1,500 per second. With only 3 consumers, each owns 2 partitions, so each faces 2,000 per second and falls behind; lag grows by 1,500 per second in total and reaches 900,000 messages after 10 minutes. With 6 consumers there is a 3,000 per second surplus, which drains that backlog in 300 seconds.1 See back-of-the-envelope estimation for this kind of arithmetic.
| Quantity | Result (computed from illustrative inputs) |
|---|---|
| Redelivery of a 45 s handler, 30 s timeout | at second 30 |
| Overlap of the two copies | 15 s |
| Move to dead-letter queue, limit of 3 receives | about second 90 |
| Duplicates after a crash, save after processing | 3 messages |
| Lost messages after a crash, save before processing | 2 messages |
| Total with naive handler, then with keys | 60, then 35 |
| Lag after 10 minutes with 3 consumers | 900,000 messages |
| Drain time with 6 consumers | 300 s |
Text description of the diagram
- Consumers beyond the partition count sit idle.
- Six consumers is the most that can share the work of six partitions.
Take 6 partitions (illustrative). In a classic consumer group, consumers beyond the partition count sit idle, and six consumers is the most that can share the work of six partitions.
Trade-offs and edge cases
A queue and a log answer different questions. Choose a queue when each message is a job to do once and then forget; choose a log when several systems need the same events, or when you may need to replay them after a bug or a new consumer.
Text description of the diagram
- A queue hides a message and deletes it after processing.
- A log keeps events until the retention limit expires.
A queue hides a message and deletes it after processing. A log keeps events until the retention limit expires. Parallelism also differs: more consumers on a queue share its messages, while in a log read by a classic consumer group the partition count is the ceiling.
Edge cases that interviewers probe:
- Order versus parallelism. For order inside one entity, key by that entity. In SQS, first in, first out (FIFO) queues keep messages with the same message group identifier in strict sequence, and later ones in the group wait until the in-flight one is deleted or its timeout expires (Amazon).
- Producer retries. FIFO queues remove duplicates introduced by a producer within a 5-minute deduplication interval (Amazon SQS FAQs); standard queues may occasionally deliver a duplicate.
- Limits. Standard queues allow approximately 120,000 in-flight messages, and a visibility timeout cannot exceed 12 hours from first receive (Amazon).
- Exactly once. Kafka's default is at-least-once, an idempotent producer option exists since version 0.11.0.0, and exactly-once processing is supported inside Kafka Streams and with transactions between Kafka topics (Confluent). Once a side effect leaves Kafka, such as an email or a payment, you need an idempotent consumer.
- Share groups. Kafka 4.0 (March 2025) introduced share groups as early access, per the Kafka Improvement Proposal (KIP) KIP-932 and the Kafka 4.0 release notes. A share group lets more consumers than partitions share a partition's records, with per-message acknowledgement, so the partition ceiling applies to classic consumer groups. Check the current release before relying on this, as of October 2026.
- Two writes. Saving to a database and publishing an event are two separate writes, and one can fail. The usual fix, called the outbox pattern, writes the event to a table in the same database transaction and lets a separate relay publish it.
- Push versus pull. A webhook pushes an event over the network to a receiver that must be up; a queue holds it until the consumer is ready.
A slow consumer shows up as lag and then as tail latency for end users. A pipeline that counts events at scale, such as an ad click aggregator, applies all of the above at once.
Pub/sub versus a queue, event sourcing and sagas
A queue delivers each message to one consumer, point to point. Publish-subscribe (pub/sub) delivers each event to every subscriber, so adding a subscriber changes nothing for the publisher. Fowler (2017) shows that "event-driven" covers different patterns. Event notification is a thin "something happened". Event-carried state transfer puts the data in the event, so receivers need not call back. Event sourcing makes the stored events the system of record, and state is rebuilt by replaying them. Events outlive code, so evolve their schema by adding fields, not renaming them.
For a workflow across services, the saga pattern replaces one distributed transaction with local transactions. Each publishes an event that triggers the next, and compensating actions undo earlier steps on failure. In choreography each service reacts to events; in orchestration a central coordinator tells each service what to do. Choreography is simple for few steps; orchestration is easier to follow as steps grow.
How to answer it in an interview
How would you use a message queue between two services, and what can go wrong?
A queue sits between the producer and the consumer, so the producer does not wait and bursts are absorbed. Delivery is at least once. If a consumer crashes or runs past the visibility timeout, the message returns, so I make the consumer idempotent with a message key, for example a payment identifier. If I need order, I key messages so related ones land on one partition, because order holds only inside a partition. In a classic consumer group, parallelism is capped by the partition count. Failing messages go to a dead-letter queue after a set number of attempts, and I alert on that queue and on consumer lag.
The spoken structure: say why the queue is there, then the delivery promise and its cost, then ordering and parallelism, then failure handling.
Common mistakes
- "Exactly-once delivery is automatic." (wrong) The Kafka default is at least once, and many exactly-once claims are narrower than they sound. (right) "Delivery is at least once, and I make the consumer idempotent."
- "Kafka keeps global order." (wrong) Order holds only within a partition. (right) "I key by entity so related events share a partition."
- "A consumed message is deleted." (wrong) True after a delete in SQS, false in Kafka, where events stay until retention expires. (right) "A queue forgets; a log remembers and supports replay."
- "The visibility timeout locks the message." (wrong) It is a lease, and a slow handler gets a duplicate. (right) "I set the timeout above the handler time or extend it."
- "More consumers always means more throughput." (wrong) Within a classic consumer group each partition goes to one consumer. (right) "In a classic consumer group, throughput is capped by the partition count."
- "A dead-letter queue fixes failures." (wrong) It only parks them. (right) "I alert on it and replay after a fix."
Follow-up questions
What is the difference between a message queue and Kafka?
A classic queue hides and then deletes a message once a consumer confirms it, while a Kafka topic is a durable log whose events stay after reading and are tracked by offsets for each consumer group, which allows replay. Kafka itself is described as a distributed publish-subscribe messaging system with persistent storage (Confluent).
Is exactly-once delivery possible?
Within Kafka, between topics, yes, with transactions and Kafka Streams; across a side effect such as a payment, the dependable answer is at-least-once delivery plus an idempotent consumer. See the payment system design for where this matters.
How do you keep message ordering in a queue?
Use a key so related messages go to the same partition, or a FIFO queue with one message group per entity. Order is then kept inside that partition or group, not across all messages.
What happens when a consumer is slower than the producer?
Messages pile up as lag. Add consumers up to the partition count in a classic group, speed up the handler, or add partitions (which remaps keys, so per-key order breaks for existing keys); the worked example shows a backlog draining once capacity exceeds arrival rate.
What is the difference between event sourcing and event-driven architecture?
Event-driven architecture is a style in which services react to events. Event sourcing is one pattern in which the stored events are the system of record and state is rebuilt by replaying them (Fowler, 2017). A system can be event-driven without event sourcing.
When would you use a webhook instead of a queue?
Use a webhook when an outside party needs a direct notification and can handle a retry; put a queue behind your own receiver so a burst or an outage does not lose events. More in the representational state transfer (REST) application programming interface (API) interview questions.
- A message queue decouples producer and consumer in time and rate, but delivery is at least once.
- Make consumers idempotent with a message key; exactly-once claims are narrower than they sound.
- A queue forgets a consumed message; a log keeps it and allows replay from an offset.
- Order holds within a partition, and in a classic consumer group parallelism is capped by the partition count.
- A dead-letter queue parks messages that keep failing; someone must still inspect them.
Sources
- Introduction to Apache Kafka (Confluent documentation) — Confluent, 8 May 2026
- Kafka message delivery semantics (Confluent documentation) — Confluent, 26 Sep 2025
- Amazon SQS visibility timeout (SQS Developer Guide) — Amazon Web Services, 26 Oct 2026
- Amazon SQS FAQs — Amazon Web Services, 26 Oct 2026
- Kafka consumers (Kafka 101 course) — Confluent Developer, 26 Oct 2026
- KIP-932: Queues for Kafka — Apache Kafka, 18 Mar 2025
- Apache Kafka blog (Kafka 4.0 release notes) — Apache Kafka, 18 Mar 2025
- What do you mean by 'Event-Driven'? — Martin Fowler, 7 Feb 2017
- Pattern: Saga — microservices.io (Chris Richardson), 26 Oct 2026