Skip to content

Infrastructure

Payment timeouts: what to do when the PSP does not respond but the charge may have happened

Learn to handle timeouts, unknown states, retries, idempotency, failover, and reconciliation without creating duplicate charges.

16 min readBy Gustavo Sanchez Palencia
Clock and interrupted connection between a payment system and a provider, representing an unknown result after a timeout

Few payment scenarios are as dangerous as a timeout.

When an API returns an explicit decline, the system has an answer. The same is true when it returns success. With a timeout, however, the application may not know whether the operation failed before reaching the processor, was processed but lost its response, or is still running somewhere in the chain.

This uncertainty completely changes the retry strategy.

Treating a timeout as “failed” may cause a second charge after the first has already taken effect. Treating it as “successful” may release a product without sufficient evidence. The safe approach is to represent uncertainty as its own state and seek evidence before taking an irreversible action.

Operational playbook: what should you do when the PSP did not respond?

Use this playbook as a proposed operational approach, adapted to the provider's documented methods and guarantees. The aim is to choose the next action based on evidence without turning a missing response into a decline or approval. When checkout stops waiting, the financial investigation is not over.

First, classify the operation and the phase of failure. Was it charge creation, authorization, capture, a query, or a refund? Did the deadline expire in the browser, your service, or communication with the PSP? Record the endpoint and logical operation without copying credentials or sensitive data into the incident. A query without a response and a capture without a response require different actions.

Second, check evidence of transmission and execution. A proven failure before anything was sent, with no other queued or in-flight execution, differs from losing the connection after sending the body. A local timeout record, generic HTTP500, or socket interruption does not prove the absence of an effect. If there is uncertainty about a proxy, queue, or earlier attempt, keep it explicit.

Third, preserve the commercial-intent identifier, attempt identifier, route, available external reference, and idempotency key used. Do not replace the attempt with a new record just to clear the on-screen error. These relationships allow a late confirmation to be recognized and reveal whether another process already attempted the same operation.

Fourth, mark the attempt as pending or indeterminate when there is no conclusion. Block actions incompatible with that state, including a second charge or fulfillment based on unproven success. Tell support and the customer that confirmation is underway and provide a way to track resolution.

Fifth, query the state when the integration supports a lookup using the appropriate reference. Confirm the response belongs to the same attempt, recipient, amount, currency, and operation type. A single empty search may reflect visibility lag or an incorrect reference; treat absence as conclusive only when documented semantics and other evidence support it.

Sixth, correlate authenticated webhooks with the attempt and process confirmation idempotently. Preserve the event and its effect, distinguishing redelivery from a new operation. Adyen's webhook handling documentation (opens in a new tab ↗), consulted on October 22, 2026, illustrates verification and duplicate handling. The payment webhooks guide explains how to integrate this path into the application.

Seventh, choose the decision branch. Confirmed favorable outcome: apply the corresponding state and prevent repetition of that operation; confirmed authorization does not mean capture or settlement. Confirmed unfavorable outcome: record the reason and assess whether policy permits another attempt, because a decline is not automatically recoverable. Proven failure before execution: an attempt can be scheduled if none is in flight and other conditions are valid. Indeterminate outcome: continue investigating and prohibit another independent financial execution while the previous one's risk remains unresolved.

Repeating the same operation under a documented idempotency guarantee differs from starting another charge. Check scope, validity, payload, and concurrency rules before using this recovery path. Adyen's idempotency documentation (opens in a new tab ↗) illustrates that guarantees have specific limits. Explore the design in idempotency for preventing duplicate charges; changing PSPs does not automatically carry that guarantee across.

Eighth, escalate conflicting or inconclusive results with an owner, available evidence, the next check, and an operational deadline defined for that flow. Contact the provider through the contracted channel when necessary. Incident age alone does not justify marking the attempt as failed. If the reference cannot be recovered, record that limitation and the available reconciliation path.

Ninth, reconcile the conclusion with later movements and correct only what evidence demonstrates. If two attempts took effect, identify both before canceling an authorization or refunding according to the applicable lifecycle. Each corrective action also needs an identity and confirmation; do not turn the correction into another duplicate.

Tenth, close the incident with the outcome trail, decision taken, and condition that allowed or blocked a retry. Record why the response was lost and test recovery in staging. When preparing for peaks, incorporate this scenario into Black Friday payment tests, rather than relying on real incidents to discover the behavior.

Entirely fictional example: a R$ 120 authorization is approved, but its response is lost. The order remains awaiting confirmation. A later authenticated and correlated webhook confirms authorization for that same attempt. The application records the result once and follows the flow's capture policy; it does not create another authorization. If it had failed over to another PSP during the uncertainty, it could end up with two authorizations for one purchase, each requiring separate tracking.

What is a timeout in a payment API?

A timeout occurs when a participant waits for a response for a defined period and that period ends before a usable conclusion arrives.

It can happen between your backend and the PSP, between the PSP and acquirer, between the acquirer and another participant, or even inside an intermediate layer of your own architecture.

To the application, all may look the same: “I did not get a response in time.”

Financially, however, the outcomes may differ.

Does a timeout mean the transaction was declined?

No.

A decline is a known decision. A timeout is the absence of a sufficient response within the expected window.

A transaction may have been approved and the application still time out if the return response is lost.

Automatically converting a timeout to declined is therefore semantically incorrect.

Does a timeout mean the transaction was approved?

No.

No response is not evidence of success.

The system must preserve uncertainty until it can query state, receive a webhook, locate the transaction through idempotency, or reconcile the effect later.

Where can a timeout occur?

It may occur before the request leaves your system, during DNS resolution, TCP connection, TLS, body transmission, provider processing, or waiting for a response.

It may also occur after the provider executed the operation but before the response arrives.

The more observability detail the application has, the better it can estimate where the failure occurred.

Even so, network logs do not always prove whether a financial effect happened.

Why is automatic retrying dangerous?

Because a payment operation may not be naturally idempotent.

If the first authorization was processed and you send a second request as a new intent, the issuer may approve both.

The result is a duplicate charge caused by the recovery attempt itself.

Retrying is safe when the system knows it is repeating the same intent under an idempotency guarantee or has confirmed that the first attempt had no effect.

What is an unknown result?

It is an operational state representing exactly what the system knows: the operation started, but there is not yet enough evidence to classify it as success or failure.

This state may feel uncomfortable from a product perspective, but it is better than false certainty.

It allows incompatible actions to be blocked, reconciliation to start, and payment state to be updated later.

Should every payment system have an unknown state?

It does not have to use that word, but it must represent the idea.

It could be “processing,” “pending_confirmation,” “uncertain,” or another domain-appropriate name.

What matters is not reducing everything to succeeded and failed when distributed reality includes a third possibility.

How does idempotency help?

An idempotency key identifies the intent of a repeatable operation.

If the client receives no response and resends the same request with the same key, a provider implementing idempotency properly may return the first execution's result rather than create another effect.

This turns a retry from a new operation into repetition of the same intent.

Does idempotency solve every timeout?

No.

It reduces duplication risk, but the system still needs to understand state.

The key may have provider-specific scope, retention windows, and rules. Some APIs may be idempotent on certain endpoints but not others.

A multi-PSP application may also be unable to reuse the same guarantee across different providers.

Can I fail over to another PSP after a timeout?

Only after resolving or controlling the previous attempt's uncertainty.

Immediately sending the same charge to another PSP can produce two authorizations.

Safe failover must establish that the first attempt had no effect or have a mechanism to neutralize the risk.

In some scenarios, waiting a few seconds for a query or webhook is better than increasing the likelihood of duplication.

How long should I wait?

There is no universal number.

The window depends on the method, provider, SLA, observed behavior, and commercial impact.

The architecture may use a short timeout for user experience and a longer window for outcome reconciliation.

For example, the API may stop blocking checkout after a few seconds while the backend continues investigating the attempt.

Is a frontend timeout a financial timeout?

No.

The browser may give up before the backend. The load balancer may use a different window from the service. The service's timeout may be shorter or longer than the HTTP client's timeout for the PSP call.

Multiple timeout layers are common.

If they are not coordinated, the frontend may display an error while the backend is still waiting and eventually confirms success.

How should layered timeouts be designed?

The outer layer must understand the behavior of the inner layers.

If the frontend waits 10 seconds but the backend can take 20, the experience must support asynchronous processing.

If the backend waits 30 seconds and the gateway cuts the connection at 15, half the responses will never reach the client.

Timeouts must be designed as a latency budget, not chosen in isolation.

What is deadline propagation?

It means passing an operation's remaining time to internal services.

If a request has only three usable seconds before expiring, it makes no sense for a downstream service to start work that may take fifteen seconds whose result nobody will receive directly.

In payments, however, canceling work does not always cancel the external effect.

The application must distinguish its request deadline from the financial transaction's lifecycle.

Does closing the connection cancel the charge?

Not necessarily.

Closing an HTTP connection is not equivalent to canceling an authorization at the processor.

The provider may continue processing after the local client gives up.

This is one reason a timeout must be treated as uncertainty.

How do you query state after a timeout?

Ideally, the operation has a stable identifier created before the call or an idempotency key that can locate the intent.

The application then uses a status endpoint or reference search to check the outcome.

If the provider supplies an ID only after creation and the response was lost, idempotency becomes even more valuable.

What if the PSP does not offer an adequate query?

Operational risk increases.

The platform may depend on a webhook, later report, or reconciliation to discover the outcome.

In that case, retry policy must be more conservative.

Limited external observability is an important factor when choosing a provider.

Does a webhook resolve the timeout?

It can resolve uncertainty when the corresponding event arrives.

But there is no guarantee it will arrive immediately.

The system must correlate the webhook with the unknown-state attempt and complete the transition idempotently.

What happens if the webhook arrives after a second attempt?

This is exactly the situation an uncontrolled architecture can create.

The second attempt may have been approved through another route. Then the first attempt's webhook confirms success.

There are now two effects for one commercial intent.

Each attempt therefore needs its own entity, and the payment must control how many financial effects are acceptable.

Must payments and attempts be separate?

Separating them helps considerably.

The payment represents the commercial intent. The attempt represents a concrete execution through a particular route.

An attempt may have an unknown result while the payment awaits resolution.

If a new attempt is authorized, the system must still monitor the earlier one until it proves no effect occurred or takes corrective action.

What is a retry storm?

It is a cascade of retries caused by a temporary failure.

If thousands of transactions time out and all are retried immediately, load increases on an already degraded provider.

This can prolong the incident and create more timeouts.

Backoff, jitter, concurrency limits, and circuit breakers help control this behavior.

Does exponential backoff work for payments?

It is useful for recoverable technical failures, but should not be applied blindly to financial operations.

Before repeating, you must know whether the operation is safe to retry.

Backoff controls frequency. Idempotency controls duplication. State controls the validity of an operation.

These are different problems.

What is a circuit breaker?

A circuit breaker temporarily stops calls to a dependency whose failures exceed a specified threshold.

In payments, it may prevent continued traffic to a degraded PSP.

But opening the circuit does not resolve attempts already in flight.

Those still require reconciliation.

Should a circuit breaker automatically reroute everything?

Not necessarily.

For new intents, another route may be appropriate.

For attempts already sent whose outcomes are uncertain, moving to another PSP may duplicate effects.

Routing must distinguish a “new transaction” from a “retry of a potentially processed attempt.”

What is a hedged request, and why is it dangerous here?

A hedged request sends parallel or near-parallel requests to reduce tail latency.

This technique can be useful for idempotent reads.

In payments, sending two concurrent authorizations to different processors is extremely risky.

Low latency does not compensate for duplicate financial effects.

How should timeout types be classified?

The team can distinguish connection, read, upstream, queue, application, and external-dependency timeouts.

This taxonomy supports observability.

For financial decisions, however, the most important classification is whether evidence indicates the request may have reached the processor.

How do logs help?

Logs containing correlation IDs, attempt IDs, idempotency keys, timestamps, routes, and call phases allow events to be reconstructed.

It is also useful to record whether a socket was established, when the body was sent, and how long each phase took when the stack exposes these details.

But logs should not be used to assert a financial outcome only the provider knows.

What should you measure?

Timeout rates by PSP, endpoint, method, country, integration version, and time window.

Also measure how many timeouts ultimately resolve as success, failure, or remain inconclusive.

This distribution reveals the real risk of misclassifying timeouts.

Why do latency percentiles matter?

Averages hide the tail.

A PSP may respond in 400 ms most of the time and take 12 seconds for a small but critical fraction.

P95, p99, and the distribution help choose timeouts that do not cut off too many legitimate transactions.

Can my application cause the timeout?

Yes.

Exhausted connection pools, blocked threads, congested event loops, slow DNS, high CPU use, internal queues, and databases may consume the budget before the external call even starts.

Blaming the PSP without breaking down latency is a common mistake.

How do you separate internal from external problems?

Use traces and metrics for each stage.

How long did the request wait in a queue? How long did acquiring a connection take? How much time was spent at the PSP? Did the service respond while the layer above lost the response?

Distributed observability reduces guesswork.

What should checkout do while the result is unknown?

Avoid saying “payment declined” when that is not known.

The interface can explain that payment is being confirmed and prevent repeated clicking.

It may also offer automatic updates or a tracking page.

The message must reflect operational truth.

Should I show a “try again” button?

Only when policy establishes that another attempt is safe.

In an unknown state, that button may be the very mechanism that creates duplicates.

It is better to wait for resolution or advise the user not to retry yet.

How should support see a timeout?

The dashboard should show that the attempt is under investigation, with identifiers and the latest evidence.

If the agent sees only “error,” they may tell the customer to pay again.

Support tools must reflect the backend's state machine.

How do you handle a capture timeout?

Capture is a financial operation on an existing authorization.

If the response is lost, repeating without idempotency may produce unexpected behavior depending on the provider.

The system must query the charge or capture state before deciding.

What about refunds?

They are even more critical.

A repeated refund may return an amount twice when the model allows multiple operations.

Each refund intent must have its own identity and be reconciled before another is created.

Is a Pix timeout the same as a card timeout?

The uncertainty principle is the same, but the lifecycle differs.

Creating a Pix request, querying a Pix payment, and initiating a refund have different semantics.

The application must use method-specific identifiers rather than force a card-authorization model onto it.

How does idempotency work across multiple PSPs?

Each PSP may have its own key and scope.

The platform should maintain an internal intent key and derive or map external keys for each attempt.

When an attempt changes PSPs, it is normally a new attempt, not an idempotent repetition of the previous one.

This distinction is central.

When can I create another attempt?

When state policy determines it is permitted.

This may follow an explicit recoverable decline, a known failure before transmission, or resolution of an uncertain attempt with no effect.

A business may also consciously accept residual risk in specific cases, but that decision must be deliberate and measurable.

How do you reconcile timeouts at the end of the day?

Maintain a queue of attempts that ended without a conclusive result.

Query providers, compare reports, and check late webhooks.

Each item must reach a known state or remain escalated as a discrepancy.

Allowing unknown results to accumulate indefinitely hides financial risk.

What should you do when a timeout creates a duplicate charge?

First, identify which attempts took effect.

Then apply the appropriate correction policy, usually canceling an open authorization or refunding when needed.

The case should also drive improvements to the retry rule that permitted duplication.

A financial incident should produce platform learning.

How do you test this scenario?

Simulate slow responses, connection loss after sending, delayed webhooks, and queries that change state.

Testing only HTTP 500 does not cover the problem.

Controlled chaos testing in staging helps validate whether the application preserves idempotency and state.

What is the difference between a timeout, a decline, and a known technical error?

A decline is an explicit negative decision.

A known technical error indicates a failure identified at a point that may or may not be safe to retry.

A timeout means the waiting window ended without a sufficient conclusion.

These categories may technically overlap, but should not automatically produce the same action.

A timeout is a state problem, not just a network problem

The most dangerous mistake is thinking a timeout is solved by increasing the HTTP client's timeout in seconds.

The cause may be the network, but the financial challenge is knowing what happened after the response became unreliable.

A robust architecture preserves attempt identity, uses idempotency, queries the provider, processes webhooks, reconciles outcomes, and permits a new operation only when state makes it safe.

In payments, admitting “I don't know yet” for a few seconds is better than creating two charges while trying to appear available.