In payments, the most dangerous failure is the one where you do not know whether something happened. A request times out: did the charge go through? If the client retries, will the customer pay twice?
Idempotency keys
Every state-changing request carries an idempotency key chosen by the client. The server records the key with the request fingerprint and the eventual response, and returns that same response for any repeat of the key.
- Store the key and request hash in the same transaction as the business change.
- Reject a reused key with a different request body.
- Expire keys after a window that covers realistic client retries.
Know your provider's guarantees
Downstream providers differ. Some support idempotency natively; others need a status query before any retry. We wrap each provider behind an adapter that makes its guarantees explicit.
A retry should be the safest thing a client can do, not the most dangerous.