Skip to content

Health & Readiness

Two probes every deployment needs, at the paths Kubernetes uses by default.

go
core.RegisterHealthRoutes(e, options)

That registers GET /healthz and GET /readyz. They go on the server rather than on an authenticated group — a probe that needs a token reports the gateway's health instead of this process's.

The two probes answer different questions

/healthz — liveness. Is this process wedged?

It touches no dependency, on purpose. The only correct answer to "should this process be restarted?" is one that cannot fail for any other reason. A liveness probe that pings the database restarts every instance of the service the moment the database hiccups, turning one outage into two.

json
{ "status": "up" }

/readyz — readiness. Can this instance serve traffic?

It probes every dependency at once and reports each one.

json
{
  "status": "degraded",
  "service": "orders",
  "took_ms": 12,
  "checks": {
    "database": { "status": "up", "critical": true, "took_ms": 4 },
    "cache":    { "status": "down", "error": "dial tcp: connection refused", "took_ms": 11 }
  }
}
StatusHTTPMeaning
up200every critical dependency answered
degraded200a non-critical dependency is down — still serving, just not everything
down503a critical dependency is down

The 503 is what takes an instance out of the load balancer without restarting it, which is what you want while a database is recovering.

What gets probed

Only what the deployment actually has. A service with no redis gets no cache check, rather than a cache check that always fails.

DependencyCritical
DB and every DBS connectionyes
MongoDB and every MongoDBSyes
Cache and every Caches entryno
MQno

"Critical" is the common case, not a rule. Ask: can this instance still do its job without it? Replace the list when the answer differs for your service.

Adding your own checks

Anything the framework cannot see — a partner API, a license server, a mounted volume:

go
core.RegisterHealthRoutes(e, options, core.HealthOptions{
  Checks: []core.HealthCheck{{
    Name:     "payments-api",
    Critical: true,
    Check: func(ctx context.Context) error {
      _, err := payments.Ping(ctx)
      return err
    },
  }},
})

Use Only instead of Checks to replace the framework's list entirely, for a service that wants to name exactly what it probes.

Respect the context

Check receives a context carrying the probe's deadline. A check that ignores it is a check that can hang the probe.

Options

go
core.HealthOptions{
  Timeout: 3 * time.Second, // bounds the whole probe
  Details: nil,             // include error text in the body
  Checks:  nil,             // extra checks, alongside the framework's
  Only:    nil,             // replace the framework's checks entirely
}

Timeout bounds the whole probe (default 3s). Checks run in parallel, so the probe takes as long as the slowest one rather than the sum — which is what lets the timeout be tight enough to be useful. A check that has not answered by then is reported as down.

Details decides whether each dependency's error text appears in the body. Left nil it follows the environment: on outside production, off in it. An error string can name a host, a user or a bucket, and a probe endpoint is often the one route nobody remembers to put behind the gateway.

Checking health from your own code

For a startup gate, a CLI, or a route of your own shape:

go
report := core.CheckHealth(ctx, options, core.HealthOptions{Timeout: time.Second})
if report.Status == core.HealthDown {
  return fmt.Errorf("dependencies not ready: %+v", report.Checks)
}

Kubernetes

yaml
livenessProbe:
  httpGet: { path: /healthz, port: 8080 }
  periodSeconds: 10
readinessProbe:
  httpGet: { path: /readyz, port: 8080 }
  periodSeconds: 5

Point liveness at /healthz and readiness at /readyz — not both at the same one. Pointing liveness at /readyz is the mistake this page exists to prevent: it restarts healthy processes because something they depend on is having a bad minute.

A probe that panics does not take the process down

Each check runs guarded. A dependency whose client panics is reported as down with "panic in health check" — the probe is the last thing that should crash the service.

Maintained by Passakon Puttasuwan & Dev Core Team.