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:
Customer
│
▼
Load Balancer
│
▼
Kubernetes
│
┌───┴───────────────┐
▼ ▼
Health Checks ASP.NET Core API
│
┌───────────────┴───────────────┐
▼ ▼ ▼
SQL Database Redis Cache Payment Gateway
Workflow:
Kubernetes starts a new application instance.
The readiness probe verifies database and cache connectivity.
Once healthy, traffic is routed to the instance.
During runtime, liveness probes monitor application responsiveness.
If the application becomes unresponsive, Kubernetes restarts the container.
If an external dependency fails, readiness checks temporarily remove the instance from load balancing until it recovers.
This strategy improves application availability while reducing failed requests during dependency outages.
Health Status Responses
ASP.NET Core health checks typically return one of three states.
| Status | Meaning | Typical Action |
|---|---|---|
| Healthy | Application is operating normally | Continue serving traffic |
| Degraded | Application is functioning with limited capability | Monitor closely |
| Unhealthy | Critical dependency failure | Remove from traffic or restart |
Using these standardized states allows monitoring platforms to respond consistently across multiple applications.
Best Practices
Monitor every critical dependency.
Separate readiness and liveness endpoints.
Keep health checks lightweight.
Avoid expensive database queries.
Return meaningful health information.
Monitor external APIs separately from internal services.
Log health failures for investigation.
Integrate health endpoints with monitoring platforms.
Review health checks whenever new infrastructure dependencies are introduced.
Common Mistakes
One common mistake is performing expensive business operations inside health checks. Health endpoints should execute quickly and avoid placing additional load on production systems.
Another issue is checking only whether the application process is running. A healthy process does not guarantee that required services such as databases or caches are available.
Developers also sometimes expose detailed health information publicly. Internal dependency details should generally be restricted to trusted monitoring systems.
Testing and Validation
Before deploying health checks, validate the following:
Database failure scenarios
Cache outages
External API failures
Startup behavior
Readiness probe transitions
Liveness probe behavior
Container restart scenarios
Load balancer integration
Regular validation ensures monitoring systems respond correctly during real production incidents.
Performance Considerations
Health checks execute frequently, especially in containerized environments.
To minimize overhead:
Keep checks lightweight.
Avoid unnecessary database queries.
Cache expensive dependency information when appropriate.
Set reasonable probe intervals.
Use asynchronous operations.
Monitor health endpoint latency.
Efficient health checks improve observability without introducing measurable application overhead.
Security Considerations
Health endpoints provide operational insights and should be secured appropriately.
Follow these recommendations:
Expose detailed health information only to trusted monitoring systems.
Avoid returning sensitive configuration values.
Protect internal endpoints behind network controls where appropriate.
Use HTTPS for health endpoints.
Log repeated health failures.
Restrict access to infrastructure diagnostics.
Production health endpoints should balance operational visibility with security.
Troubleshooting
Health Endpoint Always Reports Healthy
Verify that dependency checks have been registered correctly and that custom health checks are included in the health check pipeline.
Readiness Probe Never Succeeds
Review startup configuration and ensure required services such as databases, caches, and message brokers are available before marking the application as ready.
Kubernetes Continuously Restarts the Application
Check whether liveness probes are too aggressive or whether the application requires additional startup time before health checks begin.
External Dependency Causes Frequent Failures
Consider reporting a Degraded status instead of Unhealthy for non-critical services to avoid unnecessary removal from load balancing.
Conclusion
Health checks are a fundamental part of building reliable ASP.NET Core 10 applications. By monitoring databases, caches, external services, and custom business dependencies, applications can provide accurate health information to load balancers, Kubernetes, and monitoring platforms. Separating liveness and readiness checks, keeping health probes lightweight, and integrating them into deployment workflows helps ensure applications remain resilient, scalable, and easier to operate in production.

Join the conversation! Your thoughts help the community grow.