TL;DR: A queue absorbs bursts, survives a consumer being down, and lets the producer return before the work finishes. In exchange you lose the immediate result, take on at-least-once delivery and therefore duplicate handling, and gain a backlog you have to monitor. Add one when the work does not have to finish before the caller gets a reply.
How to approach it
Frame it as a trade rather than a best practice, because the failure mode in interviews is a candidate who adds a queue to every diagram. Name the three things it buys, then the three it costs, and give a case where you would not use one.
A strong answer
What it buys:
Burst absorption. A flash sale sends ten times the normal order rate. Synchronously, the downstream service is overwhelmed and starts failing, which fails the orders. With a queue, the messages accumulate and the consumers work through them at whatever rate they can sustain. The queue converts a capacity problem into a latency problem, which is nearly always the better one to have.
Failure isolation. If the email service is down, a synchronous call means checkout fails. With a queue, the message sits there and is processed when the consumer recovers. Nothing the customer cares about broke.
Responsiveness. The producer writes the message and returns. A checkout that must synchronously charge a card, send an email, update a warehouse and notify analytics is as slow as all four and fails if any fails. Do the charge synchronously because the customer needs the answer, and queue the other three.
What it costs, and these are real:
The caller no longer knows the outcome. You returned 202 Accepted. If the work fails later, the user has been told something happened that did not. You now need a way to communicate completion or failure: a status endpoint, a webhook, a notification. That machinery is part of the cost and is routinely forgotten in a design discussion.
At-least-once delivery, so duplicates. Practically every queue delivers a message more than once under failure: the consumer processed it and died before acknowledging, so it is redelivered. Consumers must be idempotent, usually by recording a processed-message ID and skipping repeats, or by making the operation naturally repeatable. "Exactly once" is mostly a claim about a narrow path within one system, and designing as if it were universally true is how you charge someone twice.
Ordering is not free. Most queues guarantee order only within a partition or a group. If two messages about the same order can be processed concurrently, they can land out of order. Ordering per entity means keying by entity, which limits parallelism for that entity.
A new thing to operate and monitor. Queue depth and consumer lag become metrics that matter, because a queue silently absorbing a permanently failing consumer looks healthy from the producer side while work goes undone. Poison messages need a dead letter queue, or one bad message blocks the ones behind it.
When not to use one: when the reply depends on the work having finished. A login cannot be queued. A payment authorisation the customer is waiting on cannot be queued. If the next thing that happens depends on the answer, a queue adds latency and complexity and buys nothing.
The shape I would argue for in most systems: synchronous for what the user is waiting on, queued for everything that can happen afterwards. In a checkout that is the charge synchronously, and the email, the warehouse and analytics behind a queue.
What interviewers probe next
"Queue or event stream?" A queue is usually work distribution, where one consumer takes each message and it is then gone. A log like Kafka retains messages, supports multiple independent consumers reading at their own position, and allows replay. Choose the log when several systems need the same events or you want to reprocess history.
"What do you monitor?" Queue depth, message age at the head (which is the real measure of lateness), consumer throughput, and dead letter queue size. Age matters more than depth, because a large queue draining quickly is fine and a small one that has not moved in an hour is not.
"How do you handle a message that keeps failing?" Bounded retries with backoff, then a dead letter queue with an alert. Infinite retries on a poison message is how one bad record stops a pipeline.
Common mistakes
Adding a queue to a path where the caller needs the result, which adds latency and a status-tracking problem for nothing.
Assuming exactly-once delivery and writing non-idempotent consumers.
Monitoring queue depth without message age, which hides a stalled consumer on a small queue.
No dead letter queue, so a single unprocessable message blocks everything behind it.