I'm always excited to take on new projects and collaborate with innovative minds.
Learn how to enhance ASP.NET Core Health Checks with custom probes for databases and external APIs. This guide includes full code, setup instructions, and a Health Check UI dashboard. Ideal for improving observability and ensuring services are truly ready before deployment.
Modern applications are expected to be not just functional but also resilient and observable. ASP.NET Core’s built-in health checks provide a solid foundation for monitoring the health of services. However, real-world systems often demand more than just “is the application running?”. We need visibility into the health of dependencies like databases, external APIs, and internal microservices.
In this post, we’ll go beyond the basics and explore how to extend ASP.NET Core Health Checks to include custom probes—specifically for databases and third-party APIs. This ensures your deployments are more reliable and your monitoring systems can detect issues before they cause downtime.
The default health check in ASP.NET Core typically just confirms that the app is up. In microservice or cloud-based environments, that's not enough. We also need answers to questions like:
Failing to check these before deployment can lead to production outages due to misconfigured connections, expired tokens, or dependent services being down.
To get started, install the required NuGet package:
dotnet add package AspNetCore.HealthChecks.UI
Register basic health checks in your Program.cs:
builder.Services.AddHealthChecks()
.AddSqlServer("Your-Connection-String", name: "SQL Server");
This works great for SQL Server or other out-of-the-box integrations, but what if you need something custom—say, checking an internal REST API or a Redis instance that’s not supported by default?
To illustrate, let's create two custom probes:
public class PostgresHealthCheck : IHealthCheck
{
private readonly IConfiguration _configuration;
public PostgresHealthCheck(IConfiguration configuration)
{
_configuration = configuration;
}
public async Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context,
CancellationToken cancellationToken = default)
{
var connectionString = _configuration.GetConnectionString("PostgresDb");
try
{
await using var conn = new NpgsqlConnection(connectionString);
await conn.OpenAsync(cancellationToken);
return HealthCheckResult.Healthy("Postgres is available");
}
catch (Exception ex)
{
return HealthCheckResult.Unhealthy("Postgres is unavailable", ex);
}
}
}
public class ExternalApiHealthCheck : IHealthCheck
{
private readonly HttpClient _httpClient;
public ExternalApiHealthCheck(HttpClient httpClient)
{
_httpClient = httpClient;
}
public async Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context,
CancellationToken cancellationToken = default)
{
var response = await _httpClient.GetAsync("https://api.thirdparty.com/health", cancellationToken);
if (response.IsSuccessStatusCode)
return HealthCheckResult.Healthy("Third-party API is healthy");
return HealthCheckResult.Unhealthy("Third-party API is down");
}
}
Now register them during app startup:
builder.Services.AddHttpClient<ExternalApiHealthCheck>();
builder.Services.AddHealthChecks()
.AddCheck<PostgresHealthCheck>("PostgreSQL")
.AddCheck<ExternalApiHealthCheck>("ThirdPartyAPI");
For better monitoring, integrate with HealthChecks.UI:
dotnet add package AspNetCore.HealthChecks.UI.Client
In Program.cs:
builder.Services.AddHealthChecksUI().AddInMemoryStorage();
app.MapHealthChecksUI(options =>
{
options.UIPath = "/health-ui";
});
Configure the UI in appsettings.json:
"HealthChecksUI": {
"HealthChecks": [
{
"Name": "Self",
"Uri": "https://localhost:5001/health"
}
],
"EvaluationTimeOnSeconds": 10,
"MinimumSecondsBetweenFailureNotifications": 60
}
In CI/CD pipelines, especially with Kubernetes or Azure DevOps, it's common to validate service health post-deployment. But if your readiness probe only checks for HTTP 200 from the root endpoint, you're missing failure points.
By including database and API health checks in /health/ready, you ensure that your application and its dependencies are up before it receives real traffic.
app.MapHealthChecks("/health/ready", new HealthCheckOptions
{
Predicate = check => check.Tags.Contains("ready"),
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
});
Add tags to your checks:
.AddCheck<PostgresHealthCheck>("PostgreSQL", tags: new[] { "ready" })
.AddCheck<ExternalApiHealthCheck>("ThirdPartyAPI", tags: new[] { "ready" });
Extending health checks in ASP.NET Core is a crucial step towards production-readiness and system reliability. Whether it's a database, cache, queue, or an external service—your application’s health should reflect the entire system’s condition, not just the app’s uptime.
With custom probes and proper tagging, you can make your monitoring more meaningful and your deployments safer.
For a full working sample, visit this GitHub repository:
👉 https://github.com/DheerGupta35959/aspnetcore-health-checks-custom
If you're building microservices or planning automated deployments, integrating custom health checks isn't just nice to have—it's essential.
Let your app tell you when something is wrong—before your users do.
Your email address will not be published. Required fields are marked *