Question presented to candidate: "Our payments consumer reads events from a queue and updates balances. The product team wants each event applied exactly once. Can Kafka or SQS guarantee that for us, and if not, how do you build it?"
What a strong answer should cover:
- The three delivery semantics (at-most-once, at-least-once, exactly-once) and why the order of "do the side effect" and "commit the offset or delete the message" decides which one you get when a consumer crashes
- Why exactly-once delivery over a network is not achievable in general, while exactly-once processing (the effect is applied once) is, through idempotency or by committing the effect and the progress atomically
- What Kafka actually provides: the idempotent producer (producer id plus sequence numbers, on by default since Kafka 3.0) and transactions with
read_committedconsumers, which give exactly-once for read-process-write inside Kafka, not for external side effects such as a database write or an email - What SQS actually provides: FIFO queues drop duplicate sends with the same deduplication id within a 5-minute interval; receiving and processing are still at-least-once, and standard queues can deliver duplicates
- The practical patterns: idempotent consumers with a dedup key, storing offsets in the same database transaction as the result, the outbox pattern for the producing side, and idempotency keys for external calls
Clarifying questions expected:
- Where does the side effect live: another Kafka topic, our own database, or an external system such as a payment provider or email service?
- Does each event carry a stable unique id we can deduplicate on?
Code / implementation expected: Optional — a crash simulation comparing commit-first, effect-first, an idempotent sink and a transactional offset store; the example does exactly that.