MasterController

Health Checks

Liveness, readiness, and a full report — shaped like ASP.NET Core’s health checks.

master.useHealthChecks() mounts three endpoints (AddHealthChecks() + MapHealthChecks with predicates): /health/live says the process is up, /health/ready runs the checks tagged ready, and /health runs all of them. Readiness turns Unhealthy as soon as graceful shutdown begins, so load balancers drain.

Setup#

server.js
master.useHealthChecks({
  path: '/health', livePath: '/health/live', readyPath: '/health/ready',
  checks: {
    db:    { check: () => ctx.db.canConnect(), tags: ['ready'] },
    redis: { check: pingRedis, tags: ['ready'], critical: false, timeoutMs: 2000 },
  },
  authorize: (ctx) => ctx.request.socket.remoteAddress === '127.0.0.1',
});

// add or remove checks later (e.g. from a component or hosted service)
master.healthChecks.add('queue', () => ({ status: 'Healthy', data: { depth: 3 } }), { tags: ['ready'] });
master.healthChecks.remove('queue');
  • path (/health), livePath (/health/live), readyPath (/health/ready) — pass false to disable one.
  • checks{ name: fn | { check, tags, timeoutMs, critical, description } }. critical defaults to true; timeoutMs to 5000 (timeoutMs at the top level changes the default).
  • authorize(ctx) — optional gate; a falsy result answers 403 ProblemDetails. Useful to keep the full report on the internal network.

Writing a check#

javascript
// a check returns any of these (sync or async):
() => true                                                  // Healthy
() => false                                                 // Unhealthy (or Degraded when critical: false)
() => ({ healthy: false, description: 'replica lag 9s' })   // same, with text
() => ({ status: 'Degraded', data: { lagSec: 9 } })          // explicit status + data
async () => { await db.raw('select 1'); }                   // throwing -> Unhealthy/Degraded with error

Endpoints#

EndpointRunsStatus
/health/liveno checks200 while the process runs; 503 once master.stop() begins
/health/readychecks tagged ready503 when any critical check fails; 200 Degraded for non-critical failures
/healthall checks200 for Healthy/Degraded, 503 for Unhealthy
GET /health
{
  "status": "Degraded",
  "totalDurationMs": 14,
  "uptimeSec": 86412,
  "checks": {
    "db":    { "status": "Healthy",  "durationMs": 11 },
    "redis": { "status": "Degraded", "durationMs": 3, "error": "ECONNREFUSED" },
    "queue": { "status": "Healthy",  "durationMs": 0, "data": { "depth": 3 } }
  }
}

A check that exceeds its timeoutMs is reported with error: "timed out after …". During shutdown an extra host entry ("shutting down") is added and readiness reports Unhealthy.

Kubernetes
Point livenessProbe at /health/live and readinessProbe at /health/ready; pair with master.useGracefulShutdown() from Hosted Services so pods drain before the server closes. The endpoints are served by a pipeline middleware ahead of routing, so they are anonymous by default — use the authorize option if they must be restricted.