Technical demonstration
The payment timed out. Did it go through?
Follow a fictional checkout request through a lost response. This reference design uses a simulated payment provider.
THE SCENARIO
One order, one intended payment.
A checkout sends order 1042 for processing. The provider accepts the request, but the response is lost. The customer sees a spinner and tries again. The checkout service now has two requests and an unknown outcome.
Record intent before sending.
The service assigns a payment ID and saves the request fingerprint, retry key, and dispatch event in one database transaction. A unique constraint on the merchant and retry key makes concurrent retries resolve to the same payment. A reused key with a different amount or currency is rejected.
The worker sends that same payment ID as the provider’s idempotency key. This example assumes the provider supports that key and an authoritative status lookup.
EXPLORE THE FAILURE PATHS
What happens next?
The customer retries checkout
The service finds the matching payment record and returns its current status. While the outcome is unknown, checkout shows “Confirming payment.” A lookup or a verified provider event can move the record to its confirmed state.
The provider sends the success event twice
After verifying the sender, the consumer records the provider event ID and updates the payment in one transaction. A repeated event ID leaves the payment unchanged. The order service also deduplicates fulfillment by order ID.
No confirmation arrives
A reconciliation job looks up the payment by its original reference. A confirmed result updates the order. An unavailable lookup leaves the payment pending and schedules another check. If the recovery window expires, the payment enters manual review before another charge can be attempted.
How to test the design
Have a provider stub accept the payment and drop its response. Replay the checkout request, then deliver the success event twice. Check the provider ledger for one charge, the order history for one fulfillment, and the payment record for the confirmed outcome.
Repeat with the status lookup unavailable. The expected result is a pending payment with a recovery task. The retry policy must account for how long the provider retains its idempotency keys.
Explore fintech and payments expertise →PROJECT INQUIRIES
Complex problem?
Ambitious idea?
Tell us what your team is building, where you’re stuck, and what a useful first outcome would look like.