Introduction
Most articles stop at “add retry and circuit breaker”.
Real systems fail in complex, nonlinear ways—timeouts interact with retries, retries amplify load, and circuit breakers can become global bottlenecks.
.NET 8’s Resilience Pipelines are not just a Polly replacement; they represent a new execution model for fault handling in ASP.NET Core.
This article goes beyond configuration and explores:
Pipeline execution internals
Strategy ordering and side effects
Custom resilience strategies
Per-request dynamic policies
Keyed pipelines and tenant isolation
Testing failure behavior deterministically
This is production-grade resilience engineering.
Mental Model: How a Resilience Pipeline Executes
A resilience pipeline is a decorated execution chain:
Request
↓
Timeout
↓
Retry
↓
Circuit Breaker
↓
Hedging
↓
Actual Operation
Key insight:
Order matters more than configuration
Example mistake:
Retry outside timeout → long-running retries
Timeout outside retry → retries never happen
Strategy Ordering: The Correct Default
Recommended Order
Hedging
→ Timeout
→ Retry
→ Circuit Breaker
→ Operation
Why?
Hedging needs early execution
Timeout limits total execution time
Retry handles transient faults
Circuit breaker observes final outcomes
Building a Fully Controlled Pipeline
builder.Services.AddResiliencePipeline<HttpResponseMessage>(
"advanced-pipeline",
pipeline =>
{
pipeline
.AddHedging(new HedgingStrategyOptions<HttpResponseMessage>
{
MaxHedgedAttempts = 2,
Delay = TimeSpan.FromMilliseconds(150)
})
.AddTimeout(TimeSpan.FromSeconds(2))
.AddRetry(new RetryStrategyOptions<HttpResponseMessage>
{
MaxRetryAttempts = 2,
ShouldHandle = new PredicateBuilder<HttpResponseMessage>()
.Handle<HttpRequestException>()
.HandleResult(r => !r.IsSuccessStatusCode)
})
.AddCircuitBreaker(new CircuitBreakerStrategyOptions<HttpResponseMessage>
{
FailureRatio = 0.4,
MinimumThroughput = 20,
SamplingDuration = TimeSpan.FromSeconds(30),
BreakDuration = TimeSpan.FromSeconds(10)
});
});
This pipeline:
Sends parallel requests when latency spikes
Cancels execution deterministically
Stops traffic when downstream collapses
Keyed Pipelines: Tenant-Level Isolation (Advanced)
One of the least discussed but most powerful features is keyed pipelines.
Problem
A single failing tenant trips the circuit breaker
All tenants suffer
Solution: Keyed Pipelines
builder.Services.AddResiliencePipeline<string, HttpResponseMessage>(
"tenant-pipeline",
(context, pipeline) =>
{
var tenantId = context;
pipeline.AddCircuitBreaker(new CircuitBreakerStrategyOptions
{
FailureRatio = tenantId == "premium" ? 0.7 : 0.3,
BreakDuration = TimeSpan.FromSeconds(10)
});
});
Join the conversation! Your thoughts help the community grow.