TATECHATLAS
◎ English
Web & APIs

Bound HTTP retries with a deadline and handle unknown outcomes

Separate a request timeout from the total retry budget, interpret Retry-After, and avoid duplicating writes when the server outcome is unknown.

On this page

Give the whole operation one budget and check the remaining time before every attempt and wait. Retry only the methods, errors and response statuses allowed by the API contract. Respect a valid Retry-After value without extending the deadline. A timeout does not prove that a write failed: reconcile an unknown POST outcome or use the server's documented deduplication mechanism.

Budget the whole operation

A per-attempt timeout limits one request. A total deadline limits the operation across attempts and waiting periods. Starting a fresh ten-second timeout for each retry can turn an intended ten-second operation into a much longer one.

Choose a clock and cancellation mechanism appropriate to the runtime, and check the deadline again after resuming execution. A clock check between attempts does not itself cancel an in-flight request. A complete implementation needs both scheduling checks and cancellation of work that outlives the operation.

Understand the timeout mechanism

In browsers, AbortSignal.timeout measures active time. That time can pause while a worker is suspended or a document is in the back-forward cache. Do not describe it as a universal wall-clock deadline.

If fetch receives an abort signal, it can be interrupted when that signal aborts. Combining signals does not remove the need to define an overall cancellation policy. This guide explains the policy rather than supplying a complete retry library; timers, response-body processing and cleanup must be handled by the actual implementation.

Decide which requests may be retried

HTTP idempotence describes the intended effect of repeating an identical request. Safe methods such as GET are idempotent, and PUT and DELETE are also idempotent by their defined semantics. This does not mean every repetition returns the same status or that a particular server implementation is correct.

Do not automatically retry every unsuccessful response. A permanent validation error should not enter the same policy as a transient service failure. POST and PATCH are not guaranteed idempotent, so an unknown outcome needs the API's specific reconciliation or deduplication contract.

Interpret Retry-After before scheduling

Retry-After can contain a nonnegative number of seconds or an HTTP date. A delay in seconds is measured after receiving the response. HTTP dates require a comparison with the current time and can be affected by clock differences. A missing or malformed value does not authorize an unlimited or immediate retry.

The following is an illustrative response-header fragment, not an observed response or a complete server configuration. It asks the client to wait 120 seconds. If that delay cannot fit in the remaining operation budget, stop rather than shorten the requested delay and retry earlier.

HTTP/1.1 503 Service Unavailable
Retry-After: 120

Trace one consistent timeline

Assume a hypothetical operation starts at time zero with a ten-second deadline. Attempt 1 fails, and the chosen backoff allows attempt 2 to start at time three seconds. For this example, assume its 503 response is received at that same time with Retry-After: 120.

Seven seconds remain, but the requested wait is 120 seconds. The expected decision is to stop with a reason such as retry_after_exceeds_deadline. There is no third attempt. These are constructed values used to explain the decision, not measurements from a network test.

If the same hypothetical response instead requests three seconds, waiting until time six would leave four seconds. Another attempt is possible only if the policy permits it and its work is bounded by those remaining four seconds; the timing does not promise that the request will succeed.

Bound backoff and attempt count

When the API permits retrying and supplies no usable Retry-After value, a capped backoff policy can spread attempts over time. Jitter varies waiting periods to avoid synchronized clients repeatedly arriving together. Define the cap, randomization and maximum attempt count as application policy rather than claiming the HTTP standard provides one universal algorithm.

Before sleeping, check whether the chosen wait leaves enough time for a useful next attempt. Stop when it does not. A large Retry-After value is a reason to abandon a short operation, not a reason to cap the server's requested wait and retry before it expires.

Reconcile an unknown write outcome

If a connection disappears after a write request may have been sent, the server might have committed even though the client received no answer. Repeating a side-effecting POST can create a second order or charge. Keep the distinction between confirmed success, confirmed failure and unknown outcome.

A documented status endpoint or idempotency-key contract can help reconcile the result. Reuse a key only according to that contract, including its payload and retention rules. Sending an arbitrary header does not make a server deduplicate requests, and a status lookup is not itself permission to issue a second write.

Record the reason for each decision

Useful diagnostics include the method, attempt number, remaining budget, response status, parsed wait and stop reason. Keep credentials, authorization headers and sensitive request bodies out of these records.

Distinguish a policy stop from a transport failure so that operators know whether the budget was exhausted, the server asked for a longer wait, or a write needs reconciliation. Then review representative failure cases against the API documentation. The illustrative timeline establishes arithmetic, not reliability or performance of a deployed client.

Things to check

  • One operation budget covers all attempts and waits.
  • A valid Retry-After value is not shortened to force an earlier retry.
  • Retryable methods and response statuses come from the API contract.
  • Unknown write outcomes are reconciled rather than blindly repeated.
  • Runtime cancellation and sensitive-data handling are explicit.

The timing example is hypothetical. This guide does not implement a complete retry client or claim that browser active-time cancellation enforces every wall-clock deadline. Correct behavior depends on the runtime, server semantics and application contract.

Sources

  1. MDN: Retry-After ↗
  2. MDN: idempotent methods ↗
  3. MDN: AbortSignal timeout ↗
Back to top ↑