Modern cloud-native applications must do more than simply start successfully—they need to continuously report whether they're healthy and ready to serve requests. Containers may start before dependencies are available, databases may become unreachable, or external services may fail unexpectedly.
ASP.NET Core provides a built-in Health Checks framework that integrates with orchestrators like Kubernetes, Docker, Azure App Service, and load balancers. Properly configured health checks help automate traffic routing, restarts, and monitoring.
In this article, you'll learn how to implement production-ready health checks in ASP.NET Core 11, differentiate between liveness and readiness probes, and understand how to validate your implementation using a structured testing methodology.
Note: This article focuses on implementation patterns and testing methodology. It does not include fabricated availability or performance metrics.
Why Health Checks Matter
Without health checks, infrastructure cannot determine whether an application can safely process requests.
Typical failure scenarios include:
Database connection failures
Redis unavailable
RabbitMQ disconnected
External API outages
Disk space issues
Background worker failures
Health checks allow monitoring systems to detect these failures automatically.
Understanding Health Check Types
| Probe | Purpose | Typical Response |
|---|---|---|
| Liveness | Is the application running? | Restart if unhealthy |
| Readiness | Can the application accept traffic? | Remove from load balancer |
| Startup | Has initialization completed? | Delay readiness until startup finishes |
Each probe serves a different purpose in cloud-native deployments.
Create the Project
dotnet new webapi -n HealthChecksDemo
Register Health Checks
Enable the Health Checks framework.
builder.Services.AddHealthChecks();
This registers the infrastructure required to expose health endpoints.
Map Health Check Endpoints
Expose a basic endpoint.
app.MapHealthChecks("/health");
Request:
GET /health
Successful response:
Healthy
Add a SQL Server Health Check
Install the package.
dotnet add package Microsoft.Extensions.Diagnostics.HealthChecks.SqlServer
Register the check.
builder.Services
.AddHealthChecks()
.AddSqlServer(
builder.Configuration.GetConnectionString("Default"));
If SQL Server becomes unavailable, the health endpoint reports an unhealthy state.
Add a Redis Health Check
Install:
dotnet add package AspNetCore.HealthChecks.Redis
Configure:
builder.Services
.AddHealthChecks()
.AddRedis(
"localhost:6379",
name: "redis");
This verifies Redis connectivity.
Add a Custom Health Check
Sometimes application-specific checks are required.
Example:
using Microsoft.Extensions.Diagnostics.HealthChecks;
public class StorageHealthCheck : IHealthCheck
{
public Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context,
CancellationToken cancellationToken = default)
{
var available = true;
if (!available)
return Task.FromResult(
HealthCheckResult.Unhealthy(
"Storage unavailable"));
return Task.FromResult(
HealthCheckResult.Healthy());
}
}
Register it.
builder.Services
.AddHealthChecks()
.AddCheck<StorageHealthCheck>(
"storage");
Separate Liveness and Readiness
Register tagged checks.
builder.Services
.AddHealthChecks()
.AddSqlServer(
connectionString,
tags: new[] { "ready" });
Expose separate endpoints.
app.MapHealthChecks("/health/live");
app.MapHealthChecks("/health/ready",
new HealthCheckOptions
{
Predicate = check =>
check.Tags.Contains("ready")
});
This separation allows infrastructure to distinguish between application availability and dependency readiness.
Return Detailed Health Information
Customize the response.
app.MapHealthChecks("/health",
new HealthCheckOptions
{
ResponseWriter = async (context, report) =>
{
context.Response.ContentType =
"application/json";
await context.Response.WriteAsJsonAsync(new
{
Status = report.Status.ToString(),
Results = report.Entries.Select(e => new
{
Name = e.Key,
Status = e.Value.Status.ToString()
})
});
}
});
Example response:
{
"status": "Healthy",
"results": [
{
"name": "sql",
"status": "Healthy"
},
{
"name": "redis",
"status": "Healthy"
}
]
}
Join the conversation! Your thoughts help the community grow.