Skip to main content
The Intent.AspNetCore.HealthChecks module enables comprehensive health monitoring for your ASP.NET Core application, allowing you to determine if your application and its dependencies are responding normally.

Overview

Health checks provide endpoints that external monitoring tools can query to verify your application’s health. This is essential for container orchestrators (Kubernetes, Docker Swarm), load balancers, and monitoring systems.

What Gets Generated

HealthChecksConfiguration

Configures health check endpoints and UI:
public static class HealthChecksConfiguration
{
    public static IServiceCollection AddHealthChecksConfiguration(
        this IServiceCollection services,
        IConfiguration configuration)
    {
        var healthChecksBuilder = services.AddHealthChecks();

        // Add database health check if using Entity Framework
        healthChecksBuilder.AddDbContextCheck<ApplicationDbContext>();

        // Configure health checks UI if enabled
        var healthChecksSettings = configuration
            .GetSection("HealthChecks")
            .Get<HealthChecksSettings>();

        if (healthChecksSettings?.HealthChecksUI ?? false)
        {
            services.AddHealthChecksUI(setup =>
            {
                setup.AddHealthCheckEndpoint("API Health Check", "/health");
            })
            .AddInMemoryStorage();
        }

        return services;
    }

    public static IApplicationBuilder UseHealthChecksConfiguration(
        this IApplicationBuilder app)
    {
        app.UseHealthChecks("/health", new HealthCheckOptions
        {
            ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
        });

        app.UseHealthChecks("/health/ready", new HealthCheckOptions
        {
            Predicate = check => check.Tags.Contains("ready"),
            ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
        });

        app.UseHealthChecks("/health/live", new HealthCheckOptions
        {
            Predicate = _ => false, // Exclude all checks, just ping
            ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
        });

        return app;
    }
}

Key Features

Database Checks

Monitor database connectivity and health

Dependency Checks

Check external service dependencies

Custom Checks

Create application-specific health checks

Health UI

Optional dashboard for monitoring health

Module Settings

Publish Events

Publish Events
select
default:"none"
Specify where to publish events for monitoring health status availabilityOptions:
  • none - No event publishing
  • azure-application-insights - Publish to Azure Application Insights

Health Checks UI

Health Checks UI
boolean
default:"false"
Enable Health Checks UI - a minimal UI interface that monitors your app’s health check state

Health Check Endpoints

The module creates three standard endpoints:

/health

Overall application health:
GET /health HTTP/1.1

HTTP/1.1 200 OK
Content-Type: application/json

{
  "status": "Healthy",
  "totalDuration": "00:00:00.0234567",
  "entries": {
    "ApplicationDbContext": {
      "status": "Healthy",
      "duration": "00:00:00.0123456",
      "data": {}
    },
    "Redis": {
      "status": "Healthy",
      "duration": "00:00:00.0098765",
      "data": {}
    }
  }
}

/health/ready

Readiness probe (all dependencies ready):
GET /health/ready HTTP/1.1

HTTP/1.1 200 OK

{
  "status": "Healthy"
}

/health/live

Liveness probe (application is running):
GET /health/live HTTP/1.1

HTTP/1.1 200 OK

{
  "status": "Healthy"
}

Health Status Codes

Health checks return different HTTP status codes:
  • 200 OK - Healthy
  • 503 Service Unavailable - Unhealthy
  • 200 OK (with Degraded status) - Degraded

Built-in Health Checks

Database Health Check

Automatically added for Entity Framework:
healthChecksBuilder.AddDbContextCheck<ApplicationDbContext>();

SQL Server

healthChecksBuilder.AddSqlServer(
    connectionString: configuration.GetConnectionString("DefaultConnection"),
    name: "sql-server",
    tags: new[] { "db", "sql", "ready" });

Redis

healthChecksBuilder.AddRedis(
    redisConnectionString: configuration.GetConnectionString("Redis"),
    name: "redis",
    tags: new[] { "cache", "redis", "ready" });

Azure Services

// Azure Service Bus
healthChecksBuilder.AddAzureServiceBusQueue(
    connectionString: configuration["Azure:ServiceBus:ConnectionString"],
    queueName: "orders-queue",
    name: "azure-service-bus");

// Azure Blob Storage
healthChecksBuilder.AddAzureBlobStorage(
    connectionString: configuration["Azure:Storage:ConnectionString"],
    name: "azure-blob-storage");

External HTTP Services

healthChecksBuilder.AddUrlGroup(
    new Uri("https://api.external-service.com/health"),
    name: "external-api",
    tags: new[] { "external", "ready" });

Custom Health Checks

Create application-specific health checks:

Simple Health Check

public class CustomHealthCheck : IHealthCheck
{
    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context,
        CancellationToken cancellationToken = default)
    {
        var isHealthy = CheckSomeCondition();

        if (isHealthy)
        {
            return Task.FromResult(
                HealthCheckResult.Healthy("Custom check passed"));
        }

        return Task.FromResult(
            HealthCheckResult.Unhealthy("Custom check failed"));
    }

    private bool CheckSomeCondition()
    {
        // Your custom logic here
        return true;
    }
}

// Register
services.AddHealthChecks()
    .AddCheck<CustomHealthCheck>("custom-check");

Health Check with Dependencies

public class OrderProcessingHealthCheck : IHealthCheck
{
    private readonly IOrderService _orderService;
    private readonly ILogger<OrderProcessingHealthCheck> _logger;

    public OrderProcessingHealthCheck(
        IOrderService orderService,
        ILogger<OrderProcessingHealthCheck> logger)
    {
        _orderService = orderService;
        _logger = logger;
    }

    public async Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context,
        CancellationToken cancellationToken = default)
    {
        try
        {
            var pendingCount = await _orderService
                .GetPendingOrdersCountAsync(cancellationToken);

            if (pendingCount > 1000)
            {
                return HealthCheckResult.Degraded(
                    $"High number of pending orders: {pendingCount}",
                    data: new Dictionary<string, object>
                    {
                        { "PendingOrders", pendingCount }
                    });
            }

            return HealthCheckResult.Healthy(
                $"Order processing is healthy. Pending: {pendingCount}",
                data: new Dictionary<string, object>
                {
                    { "PendingOrders", pendingCount }
                });
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Order processing health check failed");
            return HealthCheckResult.Unhealthy(
                "Failed to check order processing",
                exception: ex);
        }
    }
}

// Register
services.AddHealthChecks()
    .AddCheck<OrderProcessingHealthCheck>(
        "order-processing",
        tags: new[] { "business", "ready" });

Memory Health Check

public class MemoryHealthCheck : IHealthCheck
{
    private const long Threshold = 1024L * 1024L * 1024L; // 1 GB

    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context,
        CancellationToken cancellationToken = default)
    {
        var allocated = GC.GetTotalMemory(forceFullCollection: false);
        var data = new Dictionary<string, object>
        {
            { "AllocatedBytes", allocated },
            { "Gen0Collections", GC.CollectionCount(0) },
            { "Gen1Collections", GC.CollectionCount(1) },
            { "Gen2Collections", GC.CollectionCount(2) }
        };

        var status = allocated < Threshold 
            ? HealthStatus.Healthy 
            : HealthStatus.Degraded;

        return Task.FromResult(new HealthCheckResult(
            status,
            description: $"Reports degraded status if allocated memory >= {Threshold} bytes.",
            data: data));
    }
}

Tagging Health Checks

Organize health checks with tags:
services.AddHealthChecks()
    .AddDbContextCheck<ApplicationDbContext>(
        name: "database",
        tags: new[] { "db", "sql", "ready" })
    .AddRedis(
        configuration["Redis:ConnectionString"],
        name: "redis",
        tags: new[] { "cache", "ready" })
    .AddCheck<OrderProcessingHealthCheck>(
        "order-processing",
        tags: new[] { "business" });
Filter by tags in endpoints:
app.UseHealthChecks("/health/ready", new HealthCheckOptions
{
    Predicate = check => check.Tags.Contains("ready")
});

app.UseHealthChecks("/health/db", new HealthCheckOptions
{
    Predicate = check => check.Tags.Contains("db")
});

Health Checks UI

When enabled, provides a web interface:
services.AddHealthChecksUI(setup =>
{
    setup.SetEvaluationTimeInSeconds(30); // Check every 30 seconds
    setup.MaximumHistoryEntriesPerEndpoint(50);
    setup.AddHealthCheckEndpoint("API", "/health");
})
.AddInMemoryStorage();

app.UseHealthChecksUI(options =>
{
    options.UIPath = "/health-ui";
    options.ApiPath = "/health-ui-api";
});
Access the UI at: https://localhost:5001/health-ui

Kubernetes Integration

Liveness Probe

Checks if the container should be restarted:
apiVersion: v1
kind: Pod
metadata:
  name: my-api
spec:
  containers:
  - name: api
    image: my-api:latest
    livenessProbe:
      httpGet:
        path: /health/live
        port: 80
      initialDelaySeconds: 30
      periodSeconds: 10
      timeoutSeconds: 5
      failureThreshold: 3

Readiness Probe

Checks if the container is ready to receive traffic:
readinessProbe:
  httpGet:
    path: /health/ready
    port: 80
  initialDelaySeconds: 5
  periodSeconds: 10
  timeoutSeconds: 5
  successThreshold: 1
  failureThreshold: 3

Startup Probe

Checks if the application has started:
startupProbe:
  httpGet:
    path: /health/live
    port: 80
  initialDelaySeconds: 0
  periodSeconds: 10
  timeoutSeconds: 5
  failureThreshold: 30

Docker Compose

services:
  api:
    image: my-api:latest
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

Azure Application Insights

Publish health check events to Application Insights:
services.AddHealthChecks()
    .AddApplicationInsightsPublisher(
        instrumentationKey: configuration["ApplicationInsights:InstrumentationKey"],
        saveDetailedReport: true);

Monitoring and Alerting

Azure Monitor

Create availability test:
az monitor app-insights component create \
  --app my-api \
  --location eastus \
  --resource-group my-rg

az monitor app-insights web-test create \
  --app my-api \
  --location eastus \
  --name health-check \
  --web-test-url https://api.example.com/health

Prometheus

Export health checks to Prometheus:
services.AddHealthChecks()
    .ForwardToPrometheus();

Best Practices

  • Keep health checks fast (< 1 second)
  • Don’t perform complex operations
  • Use timeouts for external checks
  • Cache results when appropriate
  • Check critical dependencies only
  • Use readiness probes for dependencies
  • Don’t fail liveness for dependency issues
  • Implement circuit breakers for external services
  • Don’t expose sensitive information
  • Consider authentication for health endpoints
  • Use internal endpoints for detailed checks
  • Limit information in public health checks
  • Set up alerts for unhealthy states
  • Monitor health check duration
  • Track degraded states
  • Log health check failures

Troubleshooting

  • Check dependency configuration
  • Verify connection strings
  • Review health check logs
  • Test dependencies independently
  • Reduce check complexity
  • Add timeout to external checks
  • Check network connectivity
  • Review database query performance
  • Increase initialDelaySeconds
  • Adjust failureThreshold
  • Check liveness vs readiness configuration
  • Review application startup time

Installation

Intent.AspNetCore.HealthChecks

Dependencies

  • Intent.Common.CSharp
  • Intent.Modelers.Services
  • Intent.OutputManager.RoslynWeaver

NuGet Packages

Common health check packages:
<PackageReference Include="AspNetCore.HealthChecks.SqlServer" Version="*" />
<PackageReference Include="AspNetCore.HealthChecks.Redis" Version="*" />
<PackageReference Include="AspNetCore.HealthChecks.AzureServiceBus" Version="*" />
<PackageReference Include="AspNetCore.HealthChecks.Uris" Version="*" />
<PackageReference Include="AspNetCore.HealthChecks.UI" Version="*" />

Next Steps

ASP.NET Core

Learn about the core infrastructure

Controllers

Create API endpoints

Entity Framework

Configure database health checks

Build docs developers (and LLMs) love