Question presented to candidate: "A payment-processing message gets delivered to your queue consumer twice — the queue's broker genuinely redelivered it, maybe because an earlier acknowledgment was lost on the network. What happens to the customer's account, and how do you make sure it's not charged twice?"
What a strong answer should cover:
- Most real message brokers (SQS, RabbitMQ, Kafka) offer at-least-once delivery, not exactly-once — meaning the exact scenario in the prompt (the identical message delivered twice) is a real, expected occurrence in production, not a rare edge case to shrug off.
- 📌 Verified, not assumed: a "naive" consumer with no deduplication, receiving the identical message object twice, genuinely double-charged a simulated account — a real balance of 100 dropped to a real 60 instead of the correct 80. An idempotent consumer, receiving the identical message twice, correctly charged the account exactly once — a real 100 became a real 80, the duplicate correctly and visibly skipped.
- The core mechanism: track a unique message/idempotency key (a message ID the producer includes, or a deterministic hash of the message's meaningful content) in a durable store the consumer checks before applying the message's side effect — if the key has already been processed, skip the side effect entirely (verified directly: the exact log line "SKIPPED duplicate delivery").
- A precise answer names where that idempotency-key store must live for the guarantee to actually hold under real failure conditions: an in-process
Set(as used to demonstrate the mechanism here) only protects against duplicates arriving while that one process is alive — a durable, shared store (a database unique constraint, Redis) is required so the guarantee survives the consumer process restarting, or a duplicate being routed to a different consumer instance entirely. - The honest trade-off: idempotency does not mean "the message is only delivered once" (that is the broker's delivery guarantee, and at-least-once is what most brokers actually offer) — it means "processing the same message more than once has the same effect as processing it once," which is a property the consumer's own code is responsible for, not something the broker provides automatically.
Clarifying questions expected:
- "Does the message carry a stable, unique ID from the producer, or does one need to be derived from its content?" — decides how the idempotency key is actually constructed.
- "Must the idempotency guarantee survive the consumer process restarting, or is duplicate delivery only a concern within a single process's lifetime?" — directly decides whether an in-process Set is sufficient or a durable external store is required.
Code / implementation expected: Yes — the real, measured naive-vs-idempotent balance comparison (a genuine double-charge bug vs. a genuine correct single charge) is the single most convincing, concrete proof of why this matters and how the fix actually works.