Payment Operations
Payment Retries: Why a Timeout Is Not a Failed Payment
How to handle uncertain payment outcomes without creating duplicates: stable references, provider checks, webhook deduplication and operational recovery.
On this page
A customer submits a payment. The application waits for a response, then displays an error. The customer presses the button again. An operator, seeing the same error, also tries to help.
There may now be three attempts to solve one problem. If the provider accepted the first instruction before the connection timed out, another submission can create a second payment.
The missing response is a communication failure. It does not establish what happened to the money. A useful payment workflow keeps that uncertainty visible, gives every attempt a stable identity and provides a controlled way to discover the outcome.
This article sets out a practical design and evaluation approach. The examples are illustrative; the rules for a particular integration must come from that provider's contract and tested behaviour.
Separate rejection from an unknown outcome
Imagine a business sending an illustrative GBP 2,500 supplier payment. Its application records the instruction and sends it to the provider. The provider accepts it, but the response never reaches the application.
Two records now describe different parts of the same event. The local application knows that it attempted submission. The provider knows that it accepted an instruction. Until those records are connected, marking the operation as failed would overstate what the application knows.
Use separate outcomes for confirmed rejection, confirmed acceptance and an unresolved submission. The exact state names matter less than the actions they permit.
| Evidence available | What the workflow should establish next |
|---|---|
| The instruction failed local validation before any provider call. | Correct the input; no external payment was attempted. |
| The provider returned a documented, definitive rejection. | Record the reason and follow the provider's correction or resubmission rules. |
| The connection timed out after submission may have begun. | Resolve the original attempt before creating another instruction. |
| The provider confirms acceptance but settlement is pending. | Continue tracking that payment; acceptance alone does not prove settlement. |
| A status lookup returns no record. | Check the lookup scope, visibility delay and provider guarantees before treating absence as final. |
An HTTP status alone may be insufficient to decide whether a payment can be resent. Document how each integration interprets responses, transport failures and status lookups. A generic retry policy should not override those decisions.
Give the instruction a stable identity
An instruction needs a durable internal identifier before the first external attempt. Link it to the provider account, amount, currency, recipient and external reference used for submission.
A retry of that instruction should preserve its identity wherever the provider supports this. Creating a fresh reference merely because the application restarted can turn recovery into a new payment.
Idempotency is the agreement that repeating an identified request does not repeat its intended effect. Its details are provider-specific. Stripe's idempotent request documentation, for example, describes matching parameters and a retention period after which an old key may no longer protect a request. Do not assume a different payment API has the same rules.
Distinguish a retry from a changed instruction. If the customer changes the recipient or amount, route that change through the appropriate approval and cancellation process. Reusing the original key with different payment details is not a sound way to amend a payment.
Amazon's discussion of idempotent APIs explains why a caller-provided identifier expresses intent more reliably than assuming identical payloads are duplicates. Two legitimate supplier payments can have the same amount and recipient. Their business identities still differ.
Persist enough information to recover after a restart
Recovery should work when the worker that made the request no longer exists. An in-memory flag or an operator's browser session cannot provide that guarantee.
Before submission, persist the instruction and the reference that will be sent. After each attempt, retain the evidence needed to decide what can safely happen next: when it ran, which provider connection it used and the last confirmed outcome. Keep credentials and unnecessary personal data out of that record.
Consider the interruption immediately after the provider accepted the payment but before the local result was saved. The next worker should find an unresolved attempt with its original reference. It can then query the provider or follow its documented idempotent retry procedure.
Concurrency deserves the same treatment. If a scheduled worker and an operator both request recovery, they should not independently submit a payment. Enforce the processing boundary with a durable concurrency mechanism and expose the same recovery action to both paths.
Make repeated notifications harmless
The outbound request is only one place where duplication can occur. A provider notification may be delivered again, or a worker may resume after partially processing it.
Stripe's webhook guidance explicitly discusses duplicate events and event ordering. For any provider, establish its notification contract rather than relying on one delivery in a preferred sequence.
The operational question is whether processing the same external event twice can post the principal, fee or customer notification twice. Deduplicating an HTTP handler is useful only if the underlying business effects are also protected.
Retain the provider event identity where available, link it to the original instruction and apply only valid state transitions. A delayed acceptance event should not silently replace a later confirmed outcome. If two sources disagree, preserve the evidence and route the conflict for investigation.
Give customers and operators a clear next step
A customer-facing status should describe what is known. For an unresolved submission, a message such as “We are checking the payment status. Please do not submit it again” is more useful than an error followed by an active Pay button.
The operator needs more detail: the original instruction, last provider interaction, provider reference, current financial position and permitted recovery actions. Separate Check provider status from Create a new payment. Those actions have different consequences and should be recorded distinctly.
Define how long an unresolved payment may remain unattended and who owns escalation. The customer should not have to repeatedly contact support to keep an investigation moving. The staff interface should show when a check last ran and when the next action is due.
Retries also affect balances. Decide how reservations behave while the outcome is unresolved, and explain that behaviour in the account view. Releasing a reservation merely because an HTTP request timed out can make funds appear available while an external payment is still processing.
Test the interruptions, then verify the money
A successful sandbox payment establishes the happy path. Recovery needs deliberate interruption tests with provider-approved test tools or controlled substitutes.
Include at least these scenarios:
- The provider accepts an instruction, but the response is lost.
- The application restarts before persisting the response.
- Two workers attempt recovery of the same instruction.
- The same notification arrives twice, followed by an older event.
- A status lookup temporarily returns no result for an accepted instruction.
- The provider's idempotency retention window has expired while a case remains unresolved.
For each scenario, inspect the resulting provider record, local instruction, reservations, ledger entries and fees. A green application status is not enough: the test should demonstrate the expected number of payments and accounting effects.
Recovery is complete when the original instruction has an explained outcome. If a separate correcting operation is required, link it to the case and give it its own authority and audit trail. Quietly issuing a replacement hides the distinction that the investigation was meant to resolve.
Bastion platform capabilities
How Bastion fits the evaluation
Bastion's Payments & FX, Core Banking & Ledger and Bank Operations, Reporting & Audit are relevant areas to examine when reviewing a payment workflow.
Bring the provider contract and one uncertain-outcome scenario to a demonstration. Trace the same instruction from submission through recovery and accounting, and record any connector-specific work needed. A capability shown for one provider should be verified separately for another.
Discuss your payment workflow or use the software evaluation guide to define a focused pilot.





