Skip to content

Swevo/PollyHealthChecks

Repository files navigation

PollyHealthChecks

NuGet NuGet Downloads CI

ASP.NET Core health checks for Polly v8 circuit breakers — expose circuit-breaker state as /health endpoint responses so Kubernetes probes, load balancers, and monitoring dashboards can automatically react to your resilience state.

var stateProvider = new CircuitBreakerStateProvider();

services.AddResiliencePipeline("payments-api", builder =>
    builder.AddCircuitBreaker(new CircuitBreakerStrategyOptions
    {
        StateProvider = stateProvider,
        FailureRatio = 0.5,
        MinimumThroughput = 5,
        BreakDuration = TimeSpan.FromSeconds(30),
    }));

services.AddHealthChecks()
    .AddPollyCircuitBreaker("payments-api", stateProvider);  // ← one line

When the circuit opens, /health returns Unhealthy — Kubernetes stops routing traffic, zero manual intervention required.


Why PollyHealthChecks?

"How do I expose my circuit breaker state in the ASP.NET Core health endpoint?" is one of the most-asked Polly questions. Without this package you must write your own IHealthCheck, wire up CircuitBreakerStateProvider, and map the four circuit states manually. PollyHealthChecks does all of that in a single method call.

Without PollyHealthChecks With PollyHealthChecks
Write a custom IHealthCheck per circuit One AddPollyCircuitBreaker() call
Manually map all 4 circuit states Built-in Closed→Healthy, HalfOpen→Degraded, Open→Unhealthy
Re-implement for every microservice Shared package, consistent behaviour
Forget to update when you add circuits Register alongside the pipeline

Installation

dotnet add package PollyHealthChecks

Targets net6.0, net8.0, and net9.0.

Dependencies: Polly.Core 8.*, Microsoft.Extensions.Diagnostics.HealthChecks 8.*


Quick start

1. Attach a CircuitBreakerStateProvider to your pipeline

using Polly.CircuitBreaker;
using PollyHealthChecks;

var stateProvider = new CircuitBreakerStateProvider();

services.AddResiliencePipeline("downstream-api", builder =>
    builder.AddCircuitBreaker(new CircuitBreakerStrategyOptions
    {
        StateProvider  = stateProvider,
        FailureRatio   = 0.5,
        SamplingDuration  = TimeSpan.FromSeconds(10),
        MinimumThroughput = 5,
        BreakDuration  = TimeSpan.FromSeconds(30),
    }));

2. Register the health check

services.AddHealthChecks()
    .AddPollyCircuitBreaker("downstream-api", stateProvider);

3. Map the health endpoint

app.MapHealthChecks("/health");

State mapping

Circuit state Health status Meaning
Closed Healthy Normal operation
HalfOpen Degraded Testing recovery — partial traffic
Open Unhealthy (configurable) Calls rejected — dependency down
Isolated Unhealthy (configurable) Manually isolated

Kubernetes liveness & readiness probes

Use tags to split circuit breaker health into separate liveness and readiness probes:

services.AddHealthChecks()
    .AddPollyCircuitBreaker("payments-api",   paymentsStateProvider,  tags: ["ready"])
    .AddPollyCircuitBreaker("inventory-api",  inventoryStateProvider, tags: ["ready"])
    .AddPollyCircuitBreaker("auth-api",       authStateProvider,      tags: ["live", "ready"]);

// Liveness — just the critical auth circuit
app.MapHealthChecks("/health/live",  new HealthCheckOptions
{
    Predicate = r => r.Tags.Contains("live"),
});

// Readiness — all dependency circuits
app.MapHealthChecks("/health/ready", new HealthCheckOptions
{
    Predicate = r => r.Tags.Contains("ready"),
});

Kubernetes deployment:

livenessProbe:
  httpGet:
    path: /health/live
    port: 8080
  initialDelaySeconds: 5
  periodSeconds: 10

readinessProbe:
  httpGet:
    path: /health/ready
    port: 8080
  initialDelaySeconds: 5
  periodSeconds: 5

Multiple circuit breakers

Monitor every downstream dependency independently:

services.AddHealthChecks()
    .AddPollyCircuitBreaker("payments-api",   paymentsStateProvider)
    .AddPollyCircuitBreaker("inventory-api",  inventoryStateProvider, failureStatus: HealthStatus.Degraded)
    .AddPollyCircuitBreaker("auth-api",       authStateProvider,      tags: ["ready", "live"])
    .AddPollyCircuitBreaker("email-service",  emailStateProvider,     failureStatus: HealthStatus.Degraded);

Custom failure status

Demote a non-critical circuit to Degraded so a single open circuit doesn't fail the entire readiness check:

services.AddHealthChecks()
    // Critical — Unhealthy when open (default)
    .AddPollyCircuitBreaker("payments-api", paymentsStateProvider)
    // Non-critical — Degraded when open (app still serves traffic)
    .AddPollyCircuitBreaker("analytics-api", analyticsStateProvider,
        failureStatus: HealthStatus.Degraded);

HealthChecks UI integration

Works out-of-the-box with AspNetCore.HealthChecks.UI:

services.AddHealthChecksUI(opts =>
    opts.AddHealthCheckEndpoint("App", "/health"))
    .AddInMemoryStorage();

services.AddHealthChecks()
    .AddPollyCircuitBreaker("payments-api", paymentsStateProvider)
    .AddPollyCircuitBreaker("inventory-api", inventoryStateProvider);

app.MapHealthChecks("/health", new HealthCheckOptions
{
    ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse,
});
app.MapHealthChecksUI();

Full ASP.NET Core example

var builder = WebApplication.CreateBuilder(args);

var paymentsStateProvider  = new CircuitBreakerStateProvider();
var inventoryStateProvider = new CircuitBreakerStateProvider();

builder.Services.AddResiliencePipeline("payments-api", b =>
    b.AddCircuitBreaker(new CircuitBreakerStrategyOptions
    {
        StateProvider     = paymentsStateProvider,
        FailureRatio      = 0.5,
        MinimumThroughput = 5,
        BreakDuration     = TimeSpan.FromSeconds(30),
    }));

builder.Services.AddResiliencePipeline("inventory-api", b =>
    b.AddCircuitBreaker(new CircuitBreakerStrategyOptions
    {
        StateProvider     = inventoryStateProvider,
        FailureRatio      = 0.5,
        MinimumThroughput = 5,
        BreakDuration     = TimeSpan.FromSeconds(30),
    }));

builder.Services.AddHealthChecks()
    .AddPollyCircuitBreaker("payments-api",   paymentsStateProvider,  tags: ["ready", "live"])
    .AddPollyCircuitBreaker("inventory-api",  inventoryStateProvider, tags: ["ready"]);

var app = builder.Build();
app.MapHealthChecks("/health/live",  new HealthCheckOptions { Predicate = r => r.Tags.Contains("live") });
app.MapHealthChecks("/health/ready", new HealthCheckOptions { Predicate = r => r.Tags.Contains("ready") });
app.Run();

Related packages

Package Downloads Description
PollyEFCore Downloads Polly v8 resilience for EF Core queries and SaveChanges
PollyOpenAI Downloads Polly v8 resilience for OpenAI and Azure OpenAI — retry on 429, Retry-After, circuit breaker
PollyRedis Downloads Polly v8 resilience for StackExchange.Redis — retry, circuit breaker, timeout
PollySignalR Downloads Polly v8 exponential back-off reconnect policy for SignalR HubConnection
PollyGrpc Polly v8 resilience (retry, CB, timeout) for gRPC .NET clients via Interceptor
PollyKafka Polly v8 resilience (retry, CB, timeout) for Confluent.Kafka producers and consumers
PollyAzureEventHub Polly v8 for Azure Event Hubs
PollyAzureServiceBus Polly v8 resilience (retry, CB, timeout) for Azure Service Bus senders and receivers
PollyMediatR Downloads Polly v8 pipelines for MediatR request handlers
PollyElasticsearch Polly v8 for Elastic.Clients.Elasticsearch
PollyAzureKeyVault Polly v8 for Azure Key Vault
PollySendGrid Polly v8 for SendGrid
PollyMassTransit Polly v8 for MassTransit
PollyAzureTableStorage Polly v8 for Azure Table Storage
PollyMailKit MailKit SMTP email client
PollyAzureQueueStorage Azure Queue Storage QueueClient
PollyHangfire Hangfire IBackgroundJobClient
PollyBackoff Downloads Jitter, linear & custom backoff for Polly v8 retry
PollyChaos Downloads Fault & latency injection (Simmy for Polly v8)
PollyCaching Downloads Cache-aside resilience strategy for Polly v8
PollyBulkhead Downloads Bulkhead / concurrency limiter for Polly v8
PollyOpenTelemetry Downloads OpenTelemetry metrics & tracing for Polly v8

Support

If PollyHealthChecks is useful in your Kubernetes or monitoring setup, consider supporting the project:

Sponsor

💼 Need .NET / cloud-native help? Visit solidqualitysolutions.com for consulting and architecture services.

| PollyRabbitMQ | Polly v8 resilience for RabbitMQ.Client channels |

License

MIT

Packages

 
 
 

Contributors

Languages