Modern applications rarely run on a single server. They are deployed across containers, Kubernetes clusters, cloud platforms, load balancers, and microservice architectures. In these environments, simply knowing that an application process is running isn't enough. An application might be online but unable to connect to its database, communicate with external services, or process requests successfully.
Health checks provide a standardized way to determine whether an application is healthy, ready to receive traffic, or needs to be restarted. ASP.NET Core includes built-in health check support, allowing developers to expose endpoints that monitoring systems and orchestrators can use to make deployment and scaling decisions.
In this article, you'll learn how to implement production-ready health checks in ASP.NET Core 10, monitor dependencies, distinguish between liveness and readiness probes, and follow best practices for reliable application monitoring.
Why Health Checks Matter
Process Running Doesn't Mean Application Is Healthy
Consider an order processing application.
Client
│
▼
ASP.NET Core API
│
├────────► SQL Database
│
├────────► Redis Cache
│
├────────► Payment Gateway
│
└────────► Message Queue
The application process may still be running even if:
The database is unavailable.
Redis is disconnected.
External APIs are unreachable.
A message queue is offline.
Without health checks, load balancers and orchestration platforms continue routing requests to an unhealthy instance, resulting in failed requests and poor user experience.
Understanding Health Checks
What Is a Health Check?
A health check is an endpoint that reports the current state of an application and its critical dependencies.
Typical health checks verify:
Database connectivity
Cache availability
External APIs
Disk space
Message brokers
Application startup status
Health endpoints are intended for monitoring systems rather than end users.
Configuring Health Checks
Register health check services during application startup.
builder.Services.AddHealthChecks();
Expose the endpoint.
var app = builder.Build();
app.MapHealthChecks("/health");
Why This Configuration?
The AddHealthChecks() method registers the health check infrastructure, while MapHealthChecks() exposes an HTTP endpoint that monitoring systems can query.
This provides a centralized mechanism for reporting application health without adding custom controller logic.
Monitoring Database Connectivity
Applications often depend on a database.
builder.Services
.AddHealthChecks()
.AddSqlServer(
builder.Configuration.GetConnectionString(
"DefaultConnection")!);
Why Check the Database?
A running application cannot process business requests if it cannot communicate with its database.
Database health checks detect connectivity issues before users begin experiencing widespread failures.
Creating Custom Health Checks
Business-specific dependencies may require custom validation.
public sealed class PaymentGatewayHealthCheck
: IHealthCheck
{
public async Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context,
CancellationToken cancellationToken)
{
var gatewayAvailable = true;
if (!gatewayAvailable)
{
return HealthCheckResult.Unhealthy(
"Payment gateway unavailable.");
}
return HealthCheckResult.Healthy();
}
}
Register the custom check.
builder.Services
.AddHealthChecks()
.AddCheck<PaymentGatewayHealthCheck>(
"Payment Gateway");
Why Create Custom Checks?
Built-in health checks cover common infrastructure components, but many production systems rely on external services that require custom validation.
Custom health checks allow applications to verify dependencies that are unique to their business domain.
Liveness vs Readiness
Health checks generally fall into two categories.
Liveness Probe
Answers the question:
"Should this application be restarted?"
A liveness probe checks whether the application process is functioning correctly.
Typical checks include:
Process responsiveness
Deadlock detection
Runtime failures
Readiness Probe
Answers the question:
"Can this application receive traffic?"
A readiness probe validates whether required dependencies are available.
Examples include:
Database connection
Cache availability
External service connectivity
Separating these probes prevents unnecessary application restarts while ensuring unhealthy instances stop receiving requests.
End-to-End Implementation
Consider an order processing platform deployed to Kubernetes.
Architecture:
Join the conversation! Your thoughts help the community grow.