Skip to content

Automatic Retries

TurboHTTP automatically retries failed requests when it is safe to do so — specifically, when the HTTP method is idempotent (safe to repeat without side effects) and the failure is a transient network or server error.

Retries are disabled by default. Enable them by calling .WithRetry() on the builder.

How It Works

When a request fails, TurboHTTP checks three things before retrying:

  1. Is the method idempotent? — Sending the same request twice must produce the same result. Only idempotent methods are retried.
  2. Is the failure transient? — Connection drops, timeouts, and specific server-side error codes are considered transient. A 400 Bad Request is not.
  3. Has the retry limit been reached? — Each request is retried at most MaxRetries times.

If all three conditions are satisfied, TurboHTTP retries the request automatically. The caller receives either a successful response or the last error — retry attempts are transparent.

Method Retry Table

MethodRetried?Reason
GETYesIdempotent — reading a resource has no side effects
HEADYesIdempotent — same as GET, response body omitted
PUTYesIdempotent — replacing a resource produces the same result each time
DELETEYesIdempotent — deleting an already-deleted resource is still "deleted"
OPTIONSYesIdempotent — capability query with no side effects
TRACEYesIdempotent — diagnostic echo with no side effects
POSTNoNon-idempotent — sending the same POST twice could create duplicate records
PATCHNoNon-idempotent — partial updates may produce different results each time
CONNECTNoNon-idempotent — establishes a tunnel, not a repeatable operation

Status Code Retry Table

Status CodeRetry BehaviorNotes
Network failure (no response)RetriedConnection dropped, refused, or reset before any response arrived
408 Request TimeoutRetriedServer explicitly signals the request timed out and can be resent
503 Service UnavailableRetriedServer temporarily unable to handle requests; respects Retry-After
Any other 4xx / 5xxNot retriedNon-transient errors — retrying would not change the outcome

Retry-After Header

When a 408 or 503 response includes a Retry-After header, TurboHTTP parses the delay and waits before issuing the next attempt. Both formats are supported:

  • Delay in seconds: Retry-After: 30
  • HTTP date: Retry-After: Fri, 20 Mar 2026 18:00:00 GMT

If the date is in the past, the delay is treated as zero. Set RespectRetryAfter = false in the policy to ignore this header and retry immediately.

Configuration

Retries are configured via .WithRetry() on the builder:

csharp
// Enable retries with defaults: up to 3 retries, Retry-After respected
builder.Services.AddTurboHttpClient(options =>
{
    options.BaseAddress = new Uri("https://api.example.com");
})
.WithRetry();

// Custom retry settings
builder.Services.AddTurboHttpClient("api", options =>
{
    options.BaseAddress = new Uri("https://api.example.com");
})
.WithRetry(retry =>
{
    retry.MaxRetries = 5;          // retry up to 5 times (default: 3)
    retry.RespectRetryAfter = true; // honour Retry-After header (default: true)
});

Non-Retryable Scenarios

The following situations are never retried, regardless of the method or status code:

  • Request body is a stream that cannot be rewound — if the request body has been partially sent (e.g. a streaming upload), TurboHTTP cannot restart it from the beginning, so retrying would send an incomplete body.
  • Non-idempotent methodsPOST, PATCH, and CONNECT are never retried because repeating the request could create duplicate records or have unintended side effects.
  • Retry limit reached — once MaxRetries attempts have been made, the last failure is returned to the caller.
  • .WithRetry() not called — retries are disabled entirely.

Zero-Configuration Retries

The simplest way to enable retries with sensible defaults:

csharp
builder.Services.AddTurboHttpClient(options =>
{
    options.BaseAddress = new Uri("https://api.example.com");
})
.WithRetry();

.WithRetry() with no arguments retries up to 3 times and honours Retry-After delays from the server.

Released under the MIT License.