advanced 2 min answer Multiple choice

Mobile clients on poor networks retry payment requests after timeouts. Where must idempotency be enforced, what must be durable before responding, and what is the most common scoping mistake?

phonepeidempotencyretriesmobiledurability
Pick one
Show the full answer Hide the answer

Why the alternatives fail

Suppressing client retries is not available — the client cannot distinguish a lost request from a lost response, and on a poor network it must retry or the user is stranded. Unique constraints on amount and timestamp collide with the legitimate case of a user genuinely paying the same merchant the same amount twice. Relying on the provider delegates your correctness to someone else's implementation and does nothing about duplicates created inside your own system before the provider is reached.

What must be durable before responding

The critical property: the idempotency record and the state change must commit together. If you write the key first and the payment second, a crash between them makes a real request look like a duplicate forever. If you write the payment first and the key second, a retry creates a second payment.

One transaction, containing: the key, the request fingerprint, the resulting state, and the response to replay.

The scoping mistakes, in order of frequency

  • Scoped to the wrong tenant boundary. A key unique per merchant lets two merchants collide; a key unique globally lets one merchant's key guess another's. Scope is (merchant, key).
  • No request fingerprint stored, so a client that reuses a key with different parameters gets the previous response for a different payment — which is worse than a duplicate because it is silent.
  • A time-to-live shorter than the client's retry window. A key expiring in an hour while a stuck mobile client retries the next morning produces a duplicate that looks like a fresh request.
  • Only the happy path is keyed. Refunds, captures, cancellations and webhooks all need it, and the ones that get missed are the ones with lower volume and higher financial consequence.

The state nobody designs for

A concurrent retry arriving while the first is still in flight. The key exists, the response does not. Returning "duplicate" is wrong; returning success is a lie. The correct answer is a distinct in-progress response — 409 with a retry-after — and it must be designed deliberately, because under a surge this case stops being rare and becomes a meaningful share of traffic.