A practice prompt we wrote. No company or candidate report names it, so it carries no company tag.
How to answer
The replay is easy. The interviewer is watching for the race, so spend your time there.
- Say the contract first. “The same key with the same request gets the first response back, and the work runs once. Keys are scoped per client, a reused key with a different body is an error, and keys expire after a published window.” Then ask whether the work writes to your own database or calls an outside processor. That decides how close to exactly once you can get.
- Name the race first. Check the key, do the work, then save the key: two concurrent requests both miss and both charge. The claim must be one atomic step: an insert under a lock, or an upsert across processes.
- Give each key three states: absent, in flight, done. The claim stores a fingerprint of method, path and body; the result stores the status and body to replay.
- Decide what a duplicate gets while the first is in flight. Wait for the first result, bounded, then return 409. The IETF httpapi working group’s Idempotency-Key header draft, section 2.7, a draft and not an RFC, recommends 409 for a request still in progress, 422 for a key reused with a different payload and 400 for a missing key.
- Decide what gets stored. A known outcome, even a declined card, is stored and replayed. An exception means you don’t know what happened: release the key, and pass the same key to the processor so its side is safe to retry.
- Expire from completion, not creation, and give a durable claim a lease so a crashed worker cannot hold a key forever.
The trap is testing only sequential duplicates. A test with a barrier and a slow handler fails the check-then-set version.
Follow-ups
What the interviewer may ask next, once your first answer is on the table.
- The second request arrives while the first is still charging the card. What does it get back, and when?
- The handler calls an outside payment processor, and your process dies after the charge and before you store the response. What happens on the retry?
- Same key, same amount, but the client added a new optional field to the body. Is that a replay or a conflict?
- How long do you keep keys, and who needs to know that number?
Where answers go wrong
- Checking whether the key exists, doing the work, then saving the key, so two requests that arrive together both miss and both charge.
- Keying on the idempotency key alone, so a reused key with a different body silently replays the wrong response, or one client’s key collides with another’s.
- Storing a response when the handler raised, so a timeout that never charged is replayed as a failure forever, or releasing the key after an unknown outcome without passing the same key to the processor, so the retry charges again.
Answer this in two minutes
Write the answer you would say out loud. The clock starts with your first word.
Model answer
“I’ll build it in one process first, with a lock and an event per key, then show the same claim in a database. The handler I’m wrapping charges a card through an outside processor.