// Resilience & Messaging · 04
Retry with Backoff
Try again, waiting longer each time, with a little randomness.
How it fits together
- Inventory client uses / calls Attempt 1 (1 call)
- Attempt 1 fails / error path Wait 200ms ±jitter (fails)
- Wait 200ms ±jitter uses / calls Attempt 2 (retry)
- Attempt 2 fails / error path Wait 400ms ±jitter (fails again)
- Wait 400ms ±jitter uses / calls Attempt 3 OK (retry)
Spot it
- Brief blips surface as user-facing errors
- Retries from every client land in lockstep
- A recovering service gets flattened again
It costs
Retries add latency and load, and they multiply when every layer retries.
In code
services.AddHttpClient<InventoryClient>() .AddResilienceHandler("inventory", pipeline => { pipeline.AddRetry(new HttpRetryStrategyOptions { MaxRetryAttempts = 3, BackoffType = DelayBackoffType.Exponential, Delay = TimeSpan.FromMilliseconds(200), UseJitter = true, ShouldHandle = args => ValueTask.FromResult( args.Outcome.Exception is not null || (int?)args.Outcome.Result?.StatusCode is 408 or 429 or >= 500), }); // Added after the retry, so the timeout applies to each attempt. pipeline.AddTimeout(TimeSpan.FromSeconds(2)); });Go deeperThe full explanation and what to ask for · 1 min readExpandCollapse
Retry only transient faults: timeouts, 408, 429, 503, connection resets. A 400 or a validation error fails the same way every time, and retrying a non-idempotent call can do the work twice.
The classic mistake is retries without jitter. Clients that failed together back off together and return together, a thundering herd that knocks the dependency over just as it recovers. Randomising each delay spreads them out.
Retries multiply across layers: 3 retries at each of 3 hops is up to 64 calls at the bottom for one user request. Retry at one layer, cap the total with an outer timeout, and pair it with a circuit breaker so a dead dependency stops being retried at all.
Ask for it
- transient fault
- exponential backoff
- jitter
- Retry-After
- per-attempt timeout
- retry budget
Add a retry policy to the Inventory HTTP client: retry only 408, 429, 5xx and timeouts, max 3 retries, exponential backoff from 200ms with jitter, honour Retry-After, 2s per-attempt timeout inside a 10s total. Retry only GETs and requests with an idempotency key.