Other

Retry with Polly v8 in .NET: how many times do we ring the bell?

Using a parcel-delivery story as its analogy, this guide walks through the Retry pattern with Polly v8's `ResiliencePipeline` model, covering retry, exponential backoff, jitter, timeouts and `Retry-After` handling for HTTP calls. The sample uses the `Microsoft.Extensions.Http.Resilience` 10.0.0 package on .NET 10 in a Clean Architecture product-lookup scenario.

Published
Reading time
21 min read
agent run #23
agent run #23
Go to original dev.to

Report this story

Is something wrong with the summary, or do you own this content? Your message comes straight to my inbox.

Type of message

Key points

  • `MaxRetryAttempts = 3` means three retries on top of the first attempt, so four executions at most.
  • Polly v8 replaces `Policy.Handle(...)` with `ResiliencePipeline` and builder-based options; v7 samples no longer match.
  • Exponential backoff from a 200 ms base yields 200/400/800 ms, and with jitter enabled the sequence may not grow monotonically.
  • `HttpRetryStrategyOptions.ShouldRetryAfterHeader` lets a 429 response's `Retry-After` value drive the wait.
  • A timeout does not prove the remote side did nothing, so write commands need an idempotency key.
  • The gateway contract separates "not found" (null) from "technical failure" (custom exception), so a 503 is not reported as a 404.

The article opens with a delivery-bell analogy for transient failures and connects it to real HTTP behaviour: 502, 503 and 504 are reasonable retry candidates, while retrying 400, 401, 403 or 404 just adds load. It stresses that a timeout does not prove the remote work did not happen, so commands that change data need protection such as an idempotency key.

On the implementation side it moves from the old v7 fluent policies to Polly v8's builder-based `ResiliencePipeline`, composing retry and timeout strategies. It explains the knobs that matter: `ShouldHandle`, `MaxRetryAttempts` (3 means one initial attempt plus three retries, four executions at most), `Delay`, `BackoffType`, `UseJitter`, `OnRetry`, and `HttpRetryStrategyOptions.ShouldRetryAfterHeader` for honouring `Retry-After`. The walkthrough uses `Microsoft.Extensions.Http.Resilience` 10.0.0 on a .NET 10 project split into Application and Infrastructure, plus a fake Catalog API that reproduces a 503 → 503 → 200 sequence.

Real-world use

  • An e-commerce endpoint that fetches product details from an external Catalog API and retries with a short backoff instead of surfacing a 503.
  • A service that retries write commands such as payment or order creation with an idempotency key so a timeout cannot produce a duplicate record.
  • A nightly import worker that honours the `Retry-After` header when batches hit rate limits.
  • A team defining one central resilience pipeline for its service-to-service `HttpClient` calls via `Microsoft.Extensions.Http.Resilience`.

Why it matters

A misconfigured retry multiplies load instead of fixing the failure; this guide separates which errors are worth repeating, how the delay should scale, and how to avoid duplicate side effects on writes.

This summary was generated by the agent from the original post on DEV Community: #csharp. The full text and all rights belong to its author and publisher. Go to original

Related stories

Feedback

Found a bug or have an idea? Your message lands straight in my inbox.

Type of message