health-probes
v1.1.0
Published
Kubernetes-style health check probes for Node.js — framework-agnostic /livez, /readyz, /startupz, and /healthz endpoints
Maintainers
Readme
health-probes
Health check probes for Node.js. Provides liveness, readiness, startup, and health status endpoints on a separate HTTP server. Framework-agnostic — works with any Node.js application.
Installation
npm install health-probesUsage
import { checks, probes, server } from 'health-probes';
// start health server on a separate port
// default host is '127.0.0.1' for security reasons
// use host: '0.0.0.0' in k8s containers so the kubelet can reach the probes
server.start({ host: '0.0.0.0', port: 9090 });
// enable liveness immediately
probes.live.enable();
// initialize your app...
await connectToDatabase();
// register health checks
checks.register('database', () => db.ping());
// enable startup probe (initialization complete)
probes.startup.enable();
// enable readiness probe (ready for traffic)
probes.ready.enable();Graceful shutdown
// disable readiness first (stop receiving traffic)
probes.ready.disable();
await disconnectFromDatabase();
// stop health server
await server.stop();Probes
Liveness Probe
Indicates if the process is running. If this fails, the orchestrator should restart the container.
probes.live.enable(); // returns 200 OK
probes.live.disable(); // returns 503 Service UnavailableStartup Probe
Indicates if the application has finished initializing.
probes.startup.enable();
probes.startup.disable();Readiness Probe
Indicates if the application is ready to receive traffic. When disabled or when required health checks fail, returns 503.
probes.ready.enable();
probes.ready.disable();The readiness probe automatically runs all non-optional health checks and returns 503 if any fail.
Health Status
Returns detailed JSON status of all probes and health checks. Useful for debugging and dashboards.
{
"status": "healthy",
"probes": {
"live": true,
"startup": true,
"ready": true
},
"checks": {
"database": {
"status": "healthy",
"latency": 12
},
"redis": {
"status": "unhealthy",
"latency": 5003,
"error": "check \"redis\" timed out after 5000ms"
}
}
}Status values:
healthy— all checks passdegraded— optional checks failing, required checks passunhealthy— required checks failing
Health Checks
Register health checks to verify dependencies are working:
import { checks } from 'health-probes';
// return result (recommended for boolean checks)
checks.register('database', () => ({
status: db.isConnected() ? 'healthy' : 'unhealthy',
error: db.isConnected() ? undefined : 'connection lost',
}));
// throw-based (classic pattern)
checks.register('cache', async () => {
await redis.ping(); // throws if fails
});
// with options
checks.register({
name: 'external-api',
check: () => fetch('https://api.example.com/health').then(() => {}),
optional: true, // doesn't affect readiness, only health status
timeout: 10000, // custom timeout (default: 5000ms)
});The check function can either:
- Return
HealthCheckResultwith status and optional error - Return
void(completing without error = healthy) - Throw an error (= unhealthy with error message)
Unregistering Checks
register() returns an unregister function:
const unregister = checks.register({
name: 'database',
check: () => db.ping(),
});
// later...
unregister();Server Options
server.start({
host: '0.0.0.0', // default: '127.0.0.1'
port: 9090, // default: 9090
});Resolution order: explicit option > environment variable > default.
| Setting | Env Variable | Default |
| ------- | --------------- | ------------- |
| host | HEALTH_HOST | 127.0.0.1 |
| port | HEALTH_PORT | 9090 |
This means server.start() with no arguments will pick up HEALTH_HOST / HEALTH_PORT from the environment if set.
Custom Paths
By default, endpoints use Kubernetes-style paths (/livez, /readyz, /startupz, /healthz). You can customize them:
import { SimplePaths } from 'health-probes';
// use simple paths: /live, /ready, /startup, /health
server.start({ paths: SimplePaths });
// or mix and match
server.start({
paths: {
live: '/healthcheck',
ready: '/ready',
},
});Built-in path presets:
| Preset | live | startup | ready | health |
| -------------------- | -------- | ----------- | --------- | ---------- |
| K8sPaths (default) | /livez | /startupz | /readyz | /healthz |
| SimplePaths | /live | /startup | /ready | /health |
Kubernetes Configuration
apiVersion: v1
kind: Pod
spec:
containers:
- name: app
ports:
- containerPort: 3000 # app
- containerPort: 9090 # health
livenessProbe:
httpGet:
path: /livez
port: 9090
initialDelaySeconds: 0
periodSeconds: 10
startupProbe:
httpGet:
path: /startupz
port: 9090
failureThreshold: 30
periodSeconds: 2
readinessProbe:
httpGet:
path: /readyz
port: 9090
periodSeconds: 5API Reference
Server
import { server } from 'health-probes';
server.start(options?: HealthServerOptions): void;
server.stop(): Promise<void>;Probes
import { probes } from 'health-probes';
probes.live.enable(): void;
probes.live.disable(): void;
probes.live.get(): Promise<HealthProbeResult>;
probes.live.response(): Promise<Response>;
// same for startup, ready
probes.health.get(): Promise<HealthResult>;
probes.health.response(): Promise<Response>;Checks
import { checks } from 'health-probes';
checks.register(name: string, check: CheckFn): () => void;
checks.register(check: HealthCheck): () => void;
// CheckFn = () => Promise<HealthCheckResult | void> | HealthCheckResult | void
checks.getChecks(): HealthCheck[];
checks.runAll(): Promise<Record<string, HealthCheckResult>>;
checks.runRequired(): Promise<boolean>;Types
interface ProbePaths {
live?: string;
startup?: string;
ready?: string;
health?: string;
}
interface HealthServerOptions {
host?: string; // env: HEALTH_HOST, default: '127.0.0.1'
port?: number; // env: HEALTH_PORT, default: 9090
paths?: ProbePaths; // default: K8sPaths
}
interface HealthCheck {
name: string;
check: () => Promise<HealthCheckResult | void> | HealthCheckResult | void;
optional?: boolean; // default: false
timeout?: number; // default: 5000
}
interface HealthCheckResult {
status: 'healthy' | 'unhealthy';
latency?: number;
error?: string;
}
interface HealthProbeResult {
passing: boolean;
}
interface HealthResult {
status: 'healthy' | 'degraded' | 'unhealthy';
probes: {
live: boolean;
startup: boolean;
ready: boolean;
};
checks: Record<string, HealthCheckResult>;
}License
MIT
