Modern applications rarely operate in isolation. They communicate with external APIs, microservices, payment gateways, authentication providers, and cloud services. While these integrations are essential, they also introduce network failures, transient errors, and service outages.
A resilient HTTP client can recover from temporary failures without impacting users. Polly v9 provides a modern resilience framework for .NET, allowing developers to apply retry, timeout, circuit breaker, and rate-limiting strategies through reusable pipelines.
In this article, you'll learn how to build production-ready HTTP clients using Polly v9 and .NET 11, understand common resilience patterns, and apply best practices for reliable service-to-service communication.
Why HTTP Resilience Matters
External services can fail for many reasons:
Temporary network interruptions
High server load
DNS resolution failures
API rate limiting
Service restarts
Timeouts
Infrastructure failures
Without resilience, even short-lived issues can cause cascading failures throughout an application.
Common Resilience Patterns
Polly supports several resilience strategies.
| Strategy | Purpose |
|---|---|
| Retry | Retry transient failures |
| Timeout | Stop long-running requests |
| Circuit Breaker | Prevent repeated failures |
| Fallback | Return an alternative response |
| Rate Limiter | Limit outgoing requests |
| Hedging | Send backup requests when appropriate |
Each strategy addresses a different type of failure.
Project Setup
Create a Web API.
dotnet new webapi -n PollyDemo
Install the required package.
dotnet add package Microsoft.Extensions.Http.Resilience
This package integrates Polly v9 with HttpClientFactory.
Register an HTTP Client
builder.Services.AddHttpClient("WeatherApi");
Using HttpClientFactory avoids common issues such as socket exhaustion and centralizes HTTP client configuration.
Configure a Retry Policy
Configure a resilience pipeline.
builder.Services.AddHttpClient("WeatherApi")
.AddStandardResilienceHandler(options =>
{
options.Retry.MaxRetryAttempts = 3;
});
Why Retries?
Some failures are temporary. Retrying after a short delay often succeeds without requiring user intervention.
Retries are appropriate for:
HTTP 503 (Service Unavailable)
HTTP 502 (Bad Gateway)
Temporary network failures
Connection resets
Avoid retrying permanent failures such as authentication errors or invalid requests.
Configure Timeouts
Long-running requests can consume resources unnecessarily.
builder.Services.AddHttpClient("WeatherApi")
.AddStandardResilienceHandler(options =>
{
options.TotalRequestTimeout.Timeout =
TimeSpan.FromSeconds(10);
});
Timeouts ensure requests fail predictably instead of waiting indefinitely.
Configure a Circuit Breaker
A circuit breaker prevents repeated calls to an unhealthy service.
builder.Services.AddHttpClient("WeatherApi")
.AddStandardResilienceHandler(options =>
{
options.CircuitBreaker.FailureRatio = 0.5;
options.CircuitBreaker.SamplingDuration =
TimeSpan.FromSeconds(30);
});
When failures exceed the configured threshold, requests fail immediately until the external service begins recovering.
Making HTTP Requests
Inject the client.
public class WeatherService
{
private readonly HttpClient _client;
public WeatherService(
IHttpClientFactory factory)
{
_client = factory.CreateClient("WeatherApi");
}
public async Task<string> GetForecastAsync()
{
return await _client.GetStringAsync("/weather");
}
}
The configured resilience strategies are applied automatically.
Handling Transient Failures
Instead of surrounding every request with manual retry logic, Polly centralizes resilience.
Avoid repetitive code like:
try
{
return await client.GetAsync(url);
}
catch
{
// Retry manually
}
Using resilience pipelines keeps application code clean and consistent.
End-to-End Request Flow
A typical outbound request follows these steps:
Application sends an HTTP request.
Timeout policy starts.
Request reaches the external service.
If a transient failure occurs, Polly retries.
If repeated failures exceed the threshold, the circuit breaker opens.
Successful responses reset failure tracking.
The application receives the final response.
This process improves reliability while protecting both the application and external services.
Retry Strategy Considerations
Retries should be applied selectively.
Join the conversation! Your thoughts help the community grow.