Health-check answer

A health check should tell the platform whether this instance can safely receive traffic.

Separate process life from dependency readiness

Health checks matter when deploying to platforms, containers, and load balancers.

What each endpoint promises

Separate liveness from readiness. One asks whether the process is alive. The other asks whether it can serve real requests.

Check type Meaning
Liveness Process should stay running
Readiness Instance can receive traffic
Deep dependency check Useful for dashboards but can overload dependencies if called too often

Implement a bounded readiness check

app.get("/healthz", (_req, res) => {
  res.json({ ok: true });
});

app.get("/readyz", async (_req, res) => {
  await db.query("select 1");
  res.json({ ready: true });
});

This example is intentionally small. In a real codebase, the surrounding details matter: naming, error handling, tests, runtime config, permissions, and how easy the next developer can understand the change.

Choose checks from the failure model

  • Keep liveness cheap.
  • Use readiness for critical dependencies.
  • Avoid expensive checks every few seconds.
  • Return clear status codes.
  • Make deployment platform behavior explicit.

Health-check failures that create outages

  • Checking every dependency on every liveness probe.
  • Returning 200 when the app cannot serve users.
  • Making health checks require authentication.
  • Leaking internal details publicly.
  • Forgetting startup and shutdown behavior.

Explain the operational contract

Use a concrete sentence:

I used this pattern because [problem]. The main tradeoff was [tradeoff]. I verified it by [test or check].

That structure works because it shows judgment. Anyone can name a tool. Strong developers explain why they chose it, what could go wrong, and how they checked the result.

Primary references

A health endpoint is an API

A health check should tell the platform whether this instance can safely receive traffic. Keep the implementation small, verify the edge cases, and write the decision down so the next person can trust it.

Test the failure you expect the platform to detect

A health endpoint is only useful if its failure changes something correctly. Run the service locally, make the readiness dependency unavailable, and verify three observations: the endpoint changes status, the response finishes within a small timeout, and the process remains alive long enough to recover. Then restore the dependency and verify readiness returns without a restart.

In a CryptoEx-style worker, Redis might be unavailable while PostgreSQL still accepts writes. That does not automatically mean every HTTP route should be removed from service. A public market-data route and a withdrawal route have different dependencies. One global “database plus Redis plus provider” check can turn a partial outage into a total outage.

Keep the response small and avoid exposing secrets:

{
  "status": "not_ready",
  "checks": {
    "postgres": "ok",
    "redis": "timeout"
  },
  "requestId": "health-01J..."
}

The endpoint should not return hostnames, connection strings, stack traces, queue payloads, or provider credentials. Detailed diagnostics belong in authenticated observability tools.

Set an operational budget

If the platform probes every ten seconds, a health handler that waits thirty seconds is already broken. Give each dependency a short timeout, cap parallel work, and avoid expensive table scans. Record probe failures separately from application request failures so an operator can tell whether users are affected or only the monitoring path is unhealthy.

Questions to settle before adding a probe

Who consumes this endpoint: a load balancer, container orchestrator, uptime monitor, or human operator? What action follows a failure? Which dependencies are essential for this specific process, and which can degrade without removing it from service? What timeout is safely below the probe interval?

Write those answers beside the deployment configuration. Otherwise a future engineer may add one more dependency check and accidentally make every brief provider slowdown restart healthy application processes.