dotnet-health-checks
Configures health checks for database, external services, and custom application checks. Provides liveness and readiness endpoints for container orchestration.
git clone --depth 1 https://github.com/ronnythedev/dotnet-clean-architecture-skills /tmp/dotnet-health-checks && cp -r /tmp/dotnet-health-checks/skills/17-dotnet-health-checks ~/.claude/skills/dotnet-health-checksSKILL.md
# Health Checks Configuration
## Overview
Health checks monitor application dependencies:
- **Liveness** - Is the app running?
- **Readiness** - Is the app ready to serve traffic?
- **Database checks** - PostgreSQL connectivity
- **External service checks** - APIs, caches, queues
- **Custom checks** - Business logic validation
## Quick Reference
| Check Type | Purpose |
|------------|---------|
| `AddNpgSql` | PostgreSQL database |
| `AddUrlGroup` | External HTTP endpoints |
| `AddRedis` | Redis cache |
| `AddRabbitMQ` | RabbitMQ message broker |
| Custom | Application-specific checks |
---
## Template: Health Check Registration
```csharp
// src/{name}.infrastructure/HealthChecks/HealthCheckExtensions.cs
using Microsoft.Extensions.Diagnostics.HealthChecks;
namespace {name}.infrastructure.healthchecks;
public static class HealthCheckExtensions
{
public static IServiceCollection AddHealthChecks(
this IServiceCollection services,
IConfiguration configuration)
{
services.AddHealthChecks()
// ═══════════════════════════════════════════════════════════════
// DATABASE
// ═══════════════════════════════════════════════════════════════
.AddNpgSql(
configuration.GetConnectionString("Database")!,
name: "postgresql",
failureStatus: HealthStatus.Unhealthy,
tags: new[] { "db", "sql", "postgresql", "ready" })
// ═══════════════════════════════════════════════════════════════
// EXTERNAL SERVICES
// ═══════════════════════════════════════════════════════════════
.AddUrlGroup(
new Uri(configuration["AuthService:BaseUrl"]!),
name: "auth-service",
failureStatus: HealthStatus.Degraded,
tags: new[] { "external", "auth", "ready" })
// ═══════════════════════════════════════════════════════════════
// REDIS (if used)
// ═══════════════════════════════════════════════════════════════
// .AddRedis(
// configuration.GetConnectionString("Redis")!,
// name: "redis",
// tags: new[] { "cache", "redis", "ready" })
// ═══════════════════════════════════════════════════════════════
// CUSTOM CHECKS
// ═══════════════════════════════════════════════════════════════
.AddCheck<DatabaseMigrationHealthCheck>(
"database-migrations",
tags: new[] { "db", "migrations", "ready" });
return services;
}
}
```
---
## Template: Custom Health Check
```csharp
// src/{name}.infrastructure/HealthChecks/DatabaseMigrationHealthCheck.cs
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Diagnostics.HealthChecks;
namespace {name}.infrastructure.healthchecks;
internal sealed class DatabaseMigrationHealthCheck : IHealthCheck
{
private readonly ApplicationDbContext _dbContext;
public DatabaseMigrationHealthCheck(ApplicationDbContext dbContext)
{
_dbContext = dbContext;
}
public async Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context,
CancellationToken cancellationToken = default)
{
try
{
var pendingMigrations = await _dbContext.Database
.GetPendingMigrationsAsync(cancellationToken);
var pending = pendingMigrations.ToList();
if (pending.Any())
{
return HealthCheckResult.Degraded(
$"Pending migrations: {string.Join(", ", pending)}",
data: new Dictionary<string, object>
{
{ "pending_count", pending.Count },
{ "migrations", pending }
});
}
return HealthCheckResult.Healthy("All migrations applied");
}
catch (Exception ex)
{
return HealthCheckResult.Unhealthy(
"Failed to check migrations",
exception: ex);
}
}
}
```
---
## Template: Program.cs Configuration
```csharp
// src/{name}.api/Program.cs
using HealthChecks.UI.Client;
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
var app = builder.Build();
// ═══════════════════════════════════════════════════════════════
// LIVENESS: Is the app running?
// ═══════════════════════════════════════════════════════════════
app.MapHealthChecks("/health/live", new HealthCheckOptions
{
Predicate = _ => false, // No checks, just confirms app is running
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
});
// ═══════════════════════════════════════════════════════════════
// READINESS: Is the app ready to serve traffic?
// ═══════════════════════════════════════════════════════════════
app.MapHealthChecks("/health/ready", new HealthCheckOptions
{
Predicate = check => check.Tags.Contains("ready"),
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
});
// ═══════════════════════════════════════════════════════════════
// FULL: All health checks
// ═══════════════════════════════════════════════════════════════
app.MapHealthChecks("/health", new HealthCheckOptions
{
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
});
```
---
## Kubernetes Configuration
```yaml
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
spec:
template:
spec:
containers:
- name: api
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 10
periodSeconds: 30
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
```
---
## Related Skills
- `dotnet-clean-architecture` - Infrastructure layScaffolds a complete .NET solution following Clean Architecture principles with proper layer separation (API, Application, Domain, Infrastructure). Creates project structure, dependency injection setup, and cross-cutting concerns configuration.
Generates CQRS Commands with Handlers, Validators, and Request DTOs following Clean Architecture patterns. Commands represent actions that modify state and return Result types for proper error handling.
Generates CQRS Queries with Handlers and Response DTOs for read operations. Uses Dapper for optimized read queries, bypassing the domain model for better performance.
Generates Domain Entities following DDD principles with factory methods, private setters, domain events, and proper encapsulation. Supports aggregate roots, child entities, and value objects.
Generates Repository interfaces and implementations following the Repository pattern. Provides data access abstraction for aggregate roots with EF Core implementations.
Generates Entity Framework Core configurations using Fluent API. Maps domain entities to database tables with proper relationships, constraints, and conventions.
Generates RESTful API Controllers with proper routing, versioning, authorization, and MediatR integration. Follows REST conventions and Clean Architecture patterns.
Generates Minimal API endpoints following Microsoft's recommended approach. Creates fast, testable HTTP APIs with minimal code using MapGet/MapPost/MapPut/MapDelete. Preferred over controller-based APIs for new projects.