Backend coding interview
Message Queue Consumer Coding Interview Problem
What this interview round tests
Every backend that uses Kafka, SQS, or RabbitMQ eventually asks the same interview question: your queue delivers at least once — what does your consumer do about it? This problem is that question as runnable code. A message can arrive twice, arrive out of order after a retry, or fail processing five times in a row, and the consumer must produce exactly-once effects anyway.
Interviewers reach for it because it separates candidates who have used a queue from candidates who have operated one. The mechanics under test — dedupe keys, retry budgets with backoff, and the dead-letter queue as a pressure valve — are the difference between a consumer that survives a bad deploy and one that grinds a poison message forever while the backlog grows. It is a staple follow-up in SDE2 loops wherever asynchronous processing appears.
The scenario
You are handed the consumer side of a messaging system: messages are pulled from a queue, processed into side effects, retried on failure, and parked in a DLQ when they exhaust their attempts. The pipeline exists end to end, and the test suite breaks it in every dimension.
Redelivered messages apply their effects twice, a failing message is retried instantly and forever instead of backing off, messages that should be dead-lettered keep circulating, and a retry that finally succeeds still leaves duplicate side effects behind. Your job is to make consumption at-least-once on the wire but exactly-once in effect.
What you’ll practice
- At-least-once semantics: why redelivery is normal, not an error
- Idempotent processing: keying effects by message identity so replays are no-ops
- Retry policy: bounded attempts with exponential backoff, not hot loops
- Dead-letter queues: parking poison messages without losing them
- Ack/nack discipline: when a message leaves the queue, and when it must not
- Ordering hazards: a retried message overtaking its successors safely
How to approach it
Start from the identity of a message, not its payload: processing must record "I have handled message X" atomically with X’s side effects, so a redelivery finds the record and returns without acting. If the record and the effect can be written separately, there is a crash window between them — walking that window is most of the problem.
Then make failure boring. Each attempt decrements a budget; each retry waits longer than the last; and when the budget hits zero the message moves to the DLQ with its error context instead of vanishing or recirculating. The tests simulate a poison message inside a healthy stream — the grading is whether the stream keeps flowing while the poison is quarantined.
The starter repository ships with a failing test suite and a bundled verify.sh. Reviewed reference solutions are part of Gronex Pro — this page stays spoiler-free on purpose.
FAQ
Why can’t the queue just deliver each message exactly once?
Because the network can fail after processing but before the acknowledgement arrives — the broker cannot tell "processed but unacked" from "never processed", so it redelivers. Exactly-once is therefore a property your consumer builds with idempotency, not a setting a broker provides.
What is a dead-letter queue actually for?
It is the escape hatch for messages that will never succeed — malformed payloads, deleted entities, poison pills. Without one, a single bad message either blocks its stream or burns retries forever. Parking it with error context keeps throughput alive and preserves the evidence for debugging.
Do I need Kafka or RabbitMQ installed to practise this?
No. The repository models the queue, redeliveries, and failures in-process, so every duplicate and crash is deterministic, and the bundled test suite grades your consumer logic directly in Java, Python, or C++.