Health Checks
Health checks verify that a service is ready to accept connections. They’re essential for reliable dependency ordering.
Simple Health Check
The simplest form is a command string:
services: api: cmd: npm run dev healthcheck: curl -f http://localhost:3000/healthFull Health Check Configuration
For more control, use the object form:
services: api: cmd: npm run dev healthcheck: cmd: curl -f http://localhost:3000/health interval: 2s timeout: 5s retries: 30Options
cmd
Type: string
Required: Yes
The command to run. Exit code 0 = healthy, non-zero = unhealthy.
healthcheck: cmd: curl -f http://localhost:3000/healthinterval
Type: string
Required: No
Default: "2s"
Time between health check attempts.
healthcheck: cmd: pg_isready interval: 1s # Check every secondtimeout
Type: string
Required: No
Default: "5s"
Maximum time to wait for the health check command to complete.
healthcheck: cmd: curl http://localhost:3000/health timeout: 10s # Allow slow responsesretries
Type: number
Required: No
Default: 10
Number of consecutive failures before marking the service as unhealthy.
healthcheck: cmd: pg_isready retries: 30 # Try for ~60 seconds with 2s intervalCommon Health Check Patterns
HTTP Endpoint
healthcheck: cmd: curl -f http://localhost:3000/health interval: 2s retries: 30The -f flag makes curl return a non-zero exit code on HTTP errors.
PostgreSQL
healthcheck: cmd: pg_isready -h localhost -p 5432 interval: 2s retries: 30Or with authentication:
healthcheck: cmd: pg_isready -h localhost -p 5432 -U postgresRedis
healthcheck: cmd: redis-cli ping interval: 1s retries: 30Or with custom port:
healthcheck: cmd: redis-cli -p 6380 pingMySQL
healthcheck: cmd: mysqladmin ping -h localhost -u root interval: 2s retries: 30MongoDB
healthcheck: cmd: mongosh --eval "db.adminCommand('ping')" interval: 2s retries: 30Elasticsearch
healthcheck: cmd: curl -f http://localhost:9200/_cluster/health interval: 5s retries: 60TCP Port Check
For services without specific health check tools:
healthcheck: cmd: nc -z localhost 8080 interval: 1s retries: 30gRPC Service
healthcheck: cmd: grpc_health_probe -addr=localhost:50051 interval: 2s retries: 30Health Check States
A service goes through these health-related states:
- starting - Process spawned, health check running
- running - Process running, health check not configured or not yet passed
- healthy - Health check passing
- failed - Health check never passed after all retries
Without Health Checks
If no health check is configured, the service transitions directly to running once the process spawns. Dependent services will start immediately.
services: # No healthcheck - considered "started" immediately worker: cmd: npm run worker
# Depends on worker being started (not healthy) monitor: cmd: npm run monitor depends_on: - worker # Starts as soon as worker process spawnsDocker Compose Services
For Docker Compose services, DevProc auto-generates a health check that verifies the container is running:
services: postgres: compose: true # Auto-generated: docker compose ps postgres --format jsonYou can override with a custom health check:
services: postgres: compose: true healthcheck: cmd: pg_isready -h localhost -p 5432Best Practices
Set Appropriate Retries
Calculate retries based on how long the service takes to start:
# If postgres takes ~30 seconds to be readyhealthcheck: cmd: pg_isready interval: 2s retries: 20 # 2s × 20 = 40 seconds max waitUse Dedicated Health Endpoints
Create lightweight health endpoints in your services:
// Express exampleapp.get("/health", (req, res) => { res.status(200).json({ status: "ok" })})Check What Matters
For databases, check connectivity. For APIs, check the health endpoint, not an actual endpoint that does work:
# Good - lightweight checkhealthcheck: cmd: curl -f http://localhost:3000/health
# Avoid - may be slow or have side effectshealthcheck: cmd: curl -f http://localhost:3000/api/usersHandle Slow Starts
Some services (Elasticsearch, Java apps) take longer to start:
services: elasticsearch: cmd: docker run elasticsearch:8 healthcheck: cmd: curl -f http://localhost:9200 interval: 5s timeout: 10s retries: 60 # Wait up to 5 minutes