Deploying an application successfully doesn't guarantee that it remains healthy in production. Databases become unavailable, external APIs fail, message brokers disconnect, and disk space can run low without immediately crashing the application.
ASP.NET Core includes built-in Health Checks that allow monitoring systems such as Kubernetes, Azure App Service, Docker, and load balancers to determine whether an application is healthy and ready to receive traffic. Properly implemented health checks improve reliability, reduce downtime, and enable automatic recovery when failures occur.
Rather than exposing a simple "Application is running" endpoint, this article explains how to build meaningful health checks that accurately reflect your application's health.
Note: A healthy application isn't just one that is running—it must also be able to communicate with its critical dependencies such as databases, caches, message queues, and external services.
Why Health Checks Matter
Without health checks:
Failed instances continue receiving traffic.
Deployment failures go unnoticed.
Load balancers cannot detect unhealthy servers.
Kubernetes cannot restart failed containers automatically.
Infrastructure teams have limited visibility into application health.
Health checks allow orchestration platforms to make intelligent decisions based on the current state of the application.
Types of Health Checks
Different health checks serve different purposes.
| Health Check | Purpose |
|---|---|
| Liveness | Determines whether the application is running |
| Readiness | Determines whether the application is ready to receive requests |
| Startup | Indicates whether application initialization has completed |
| Dependency | Verifies connectivity to databases, caches, or external services |
Using separate endpoints for different health states provides more accurate monitoring.
Health Check Architecture
flowchart LR
A[Monitoring System]
B[Health Endpoint]
C{Healthy?}
D[ASP.NET Core API]
E[(SQL Server)]
F[(Redis)]
G[External API]
A --> B
B --> C
C -->|Healthy| D
C -->|Check Dependencies| E
C -->|Check Dependencies| F
C -->|Check Dependencies| G
The monitoring system periodically calls the health endpoint, which verifies both the application and its dependencies.
Registering Health Checks
Add health checks during application startup.
builder.Services.AddHealthChecks();
This registers the built-in health check infrastructure.
Exposing a Health Endpoint
Map the health endpoint.
var app = builder.Build();
app.MapHealthChecks("/health");
app.Run();
A request to /health returns the application's current health status.
Checking SQL Server
Monitor database connectivity by registering a SQL Server health check.
builder.Services.AddHealthChecks()
.AddSqlServer(
connectionString,
name: "sql-server");
If SQL Server becomes unavailable, the health endpoint automatically reports the failure.
Checking Redis
Applications using distributed caching should also monitor Redis availability.
builder.Services.AddHealthChecks()
.AddRedis(
"localhost:6379",
name: "redis");
This ensures the cache layer is functioning correctly before the application receives traffic.
Creating a Custom Health Check
Some application-specific dependencies require custom validation.
public class PaymentGatewayHealthCheck
: IHealthCheck
{
public async Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context,
CancellationToken cancellationToken = default)
{
var reachable = await PaymentGateway.PingAsync();
return reachable
? HealthCheckResult.Healthy()
: HealthCheckResult.Unhealthy(
"Payment gateway unavailable.");
}
}
Register the custom health check.
builder.Services.AddHealthChecks()
.AddCheck<PaymentGatewayHealthCheck>(
"payment-gateway");
Custom health checks allow monitoring of business-critical services that aren't covered by built-in providers.
Health Status Responses
ASP.NET Core reports one of three health states.
Join the conversation! Your thoughts help the community grow.