Polly v8 resilience pipelines for MediatR — add retry, timeout, circuit-breaker, rate-limiting, hedging and chaos engineering to any MediatR request handler with a single line of registration. No changes to handler code required.
services.AddPollyMediatR(pipeline =>
pipeline
.AddRetry(new RetryStrategyOptions
{
MaxRetryAttempts = 3,
Delay = TimeSpan.FromMilliseconds(200),
ShouldHandle = new PredicateBuilder().Handle<Exception>(),
})
.AddTimeout(TimeSpan.FromSeconds(5)));Every IRequest<T> handler is now automatically wrapped with retry + timeout — zero changes to existing handlers.
MediatR's IPipelineBehavior<TRequest, TResponse> is the natural place to apply cross-cutting resilience concerns, but wiring it up with Polly v8 requires boilerplate. PollyMediatR does the wiring for you.
| Without PollyMediatR | With PollyMediatR |
|---|---|
Write a custom IPipelineBehavior per pipeline |
One AddPollyMediatR(...) call |
Manually inject ResiliencePipeline into each behavior |
Pipeline registered & injected automatically |
| Duplicate retry/timeout logic across query & command handlers | Single pipeline applied to all handlers |
| Must update handlers to apply new resilience policies | Zero changes to existing handlers |
dotnet add package PollyMediatRTargets net6.0, net8.0, and net9.0.
Dependencies: Polly.Core 8.*, MediatR 12.*, Microsoft.Extensions.DependencyInjection.Abstractions 8.*
using Polly.Retry;
using PollyMediatR;
services.AddPollyMediatR(pipeline =>
pipeline.AddRetry(new RetryStrategyOptions
{
MaxRetryAttempts = 3,
Delay = TimeSpan.FromMilliseconds(200),
BackoffType = DelayBackoffType.Exponential,
ShouldHandle = new PredicateBuilder().Handle<Exception>(),
}));var pipeline = new ResiliencePipelineBuilder()
.AddRetry(new RetryStrategyOptions { ... })
.AddTimeout(TimeSpan.FromSeconds(10))
.Build();
services.AddPollyMediatR(pipeline);// Handler — no Polly code needed
public class GetOrderHandler : IRequestHandler<GetOrderQuery, Order>
{
public async Task<Order> Handle(GetOrderQuery request, CancellationToken ct)
{
return await _db.Orders.FindAsync(request.Id, ct); // retried automatically
}
}
// At the call site — identical to normal MediatR usage
var order = await mediator.Send(new GetOrderQuery(id));var builder = WebApplication.CreateBuilder(args);
builder.Services.AddMediatR(cfg =>
cfg.RegisterServicesFromAssemblyContaining<Program>());
builder.Services.AddPollyMediatR(pipeline =>
pipeline
.AddRetry(new RetryStrategyOptions
{
MaxRetryAttempts = 3,
Delay = TimeSpan.FromMilliseconds(100),
BackoffType = DelayBackoffType.Exponential,
ShouldHandle = new PredicateBuilder()
.Handle<HttpRequestException>()
.Handle<TimeoutException>(),
})
.AddTimeout(TimeSpan.FromSeconds(30))
.AddCircuitBreaker(new CircuitBreakerStrategyOptions
{
FailureRatio = 0.5,
MinimumThroughput = 10,
SamplingDuration = TimeSpan.FromSeconds(30),
BreakDuration = TimeSpan.FromSeconds(15),
}));Polly strategies are applied outer-to-inner (left-to-right). The recommended order is:
[Timeout] → [Retry] → [Circuit Breaker] → [Handler]
pipeline
.AddTimeout(TimeSpan.FromSeconds(10)) // 1. Overall deadline
.AddRetry(retryOptions) // 2. Retry on failure
.AddCircuitBreaker(cbOptions) // 3. Open circuit if overloadedUse PollyChaos to harden your handlers in test/staging:
services.AddPollyMediatR(pipeline =>
pipeline
.AddRetry(retryOptions)
.AddChaosFault(injectionRate: 0.1)); // inject faults 10% of the time| Package | Downloads | Description |
|---|---|---|
| PollyHealthChecks | ASP.NET Core health checks for Polly v8 circuit breakers — expose circuit-breaker state (Closed, HalfOpen, Open, Isolated) as /health endpoint responses | |
| PollyOpenTelemetry | OpenTelemetry instrumentation for Polly v8 resilience pipelines | |
| PollyBackoff | Backoff delay strategies for Polly v8 resilience pipelines | |
| PollyGrpc | Polly v8 resilience interceptor for gRPC | |
| PollyEFCore | Polly v8 resilience pipelines for Entity Framework Core — wrap every EF Core query and SaveChanges with retry, timeout and circuit-breaker via a single AddPollyResilience() call | |
| PollyRabbitMQ | Polly v8 resilience for RabbitMQ.Client v7+ — retry, circuit-breaker, and timeout for IChannel operations, with built-in RabbitMqTransientErrors predicate covering AlreadyClosedException, BrokerUnreachableException, OperationInterruptedException, and ConnectFailureException | |
| PollyMailKit | Polly v8 resilience pipelines for MailKit — retry, timeout, and circuit-breaker for SmtpClient.SendAsync and any MailKit SMTP operation | |
| PollyMassTransit | Polly v8 resilience pipelines for MassTransit — retry, timeout, and circuit-breaker for IBus.Publish and ISendEndpointProvider.Send | |
| PollyOpenAI | Polly v8 resilience for OpenAI and Azure OpenAI API calls | |
| PollyAzureEventHub | Polly v8 resilience pipelines for Azure Event Hubs — retry, timeout, and circuit-breaker for EventHubProducerClient and EventHubConsumerClient | |
| PollySignalR | Polly v8 reconnect policy for SignalR | |
| PollyElasticsearch | Polly v8 resilience pipelines for Elastic.Clients.Elasticsearch 8+ — retry, timeout, and circuit-breaker for any Elasticsearch operation, plus a built-in ElasticTransientErrors predicate covering rate limiting (429), service unavailability (503), gateway timeouts (504), and connection failures | |
| PollyHangfire | Polly v8 resilience pipelines for Hangfire — retry, timeout, and circuit-breaker for IBackgroundJobClient.Enqueue and Schedule | |
| PollySendGrid | Polly v8 resilience pipelines for SendGrid — retry, timeout, and circuit-breaker for ISendGridClient.SendEmailAsync | |
| PollyAzureKeyVault | Polly v8 resilience pipelines for Azure Key Vault — retry, timeout, and circuit-breaker for SecretClient, KeyClient, and CertificateClient | |
| PollyAzureQueueStorage | Polly v8 resilience pipelines for Azure Queue Storage — retry, timeout, and circuit-breaker for Azure.Storage.Queues QueueClient | |
| PollyRedis | Polly v8 resilience for StackExchange.Redis | |
| PollyAzureServiceBus | Polly v8 resilience for Azure Service Bus — retry, circuit breaker, and timeout for sending and receiving messages | |
| PollyKafka | Polly v8 resilience for Confluent.Kafka — retry, circuit breaker, and timeout for producers and consumers | |
| PollyAzureTableStorage | Polly v8 resilience pipelines for Azure Table Storage — retry, timeout, and circuit-breaker for Azure.Data.Tables TableClient | |
| PollyCaching | A caching resilience strategy for Polly v8 pipelines | |
| PollyChaos | Chaos engineering and fault-injection resilience strategies for Polly v8 pipelines | |
| PollyBulkhead | Bulkhead isolation strategy for Polly v8 resilience pipelines |
The author of this package is available for consulting on Polly v8 resilience, Azure cloud architecture, and clean .NET design.
→ solidqualitysolutions.com · LinkedIn
MIT