A client sends a charge and the connection drops. It can't tell whether the charge happened. The only safe thing it can do is send it again.
A key says "if you send this again, nothing new happens". The part people forget is the "for how long".
Scroll to advance. The figure keeps running while you read.
A client sends a charge and the connection drops. It can't tell whether the charge happened. The only safe thing it can do is send it again.
The client creates one key per intent and sends it with every attempt. The server stores the key with the result. A repeat gets the stored result back.
Two attempts can arrive together. The first INSERT of the key wins. The other is told the request is in progress and to ask again shortly.
If the payload changed, it isn't the same request. Store a hash of the body with the key and reject a mismatch instead of replaying the wrong answer.
Keys are not kept forever. A common choice is 24 hours. After that, the same request is a new charge. The key was always a promise with an expiry date.
The window must be longer than the longest retry anyone will make: queues that redeliver, phones that were offline, batch jobs that replay a day. Retries arrive later than you expect.
Write three things in the API docs: how long a key lives, what it is scoped to, and what is stored: the full response, not just "seen".
Related machine: An idempotent ledger →