Article focus
One customer intent can reach the backend more than once
Double clicks, timeouts and provider retries are expected payment behavior.
A customer may submit payment twice after a slow connection, and a provider may redeliver the same webhook after a timeout. Without idempotency, these normal network conditions can create duplicate payment attempts, orders or receipts.
An idempotency key tells the backend that a command has already been processed. The backend can return the saved result instead of running the operation again.
- Protect payment creation.
- Protect webhook delivery.
- Protect fiscal and refund commands.
Store the key with the business operation
The key belongs to a command and its immutable input, not only to HTTP transport.
Associate a key with an operation type such as create payment, process webhook or create refund. A unique constraint prevents concurrent requests from creating the same operation twice.
Store a request fingerprint alongside the key. If the same key is later sent with a different amount, currency or order id, return a conflict rather than silently accepting a new command.
- Use key plus operation type as a uniqueness boundary.
- Keep an immutable request fingerprint.
- Return a saved result for a matching retry.
Idempotency works with a state machine
It prevents duplicate commands; transition rules prevent invalid business changes.
A payment already marked paid should not move back to pending when an old callback arrives. Idempotency identifies duplicate delivery, while a state machine defines whether a new event is allowed to alter the payment lifecycle.
Treat a refund as a new auditable event rather than a failed payment. This keeps the financial record clear and makes CRM, ERP and fiscal processes easier to reconcile.
- Do not overwrite final states with stale events.
- Log duplicate deliveries.
- Keep refund transitions distinct from failures.
FAQ
Should an order and a payment use the same idempotency key?
Usually no. Keep keys scoped to the command, such as payment creation, webhook delivery or fiscal task.
What if the same key arrives with another amount?
Reject it as a conflict after comparing the stored request fingerprint.
Are idempotency keys only for POST requests?
They are useful for any command that creates or changes state, including refunds and asynchronous event delivery.