Skip to content

Endpoints

wiki edited this page Sep 4, 2026 · 1 revision

Endpoints

Three routes, on a dedicated router at :9091 by default.

Path Answers Use as
/live is the process alive Kubernetes livenessProbe
/ready can it serve traffic Kubernetes readinessProbe
/status everything known operators, dashboards

Paths are configurable (WithLivePath, WithReadyPath, WithStatusPath).

Why a separate listener

An operational endpoint on the application's own port stops answering exactly when you need it — when the application listener is saturated, when a rate limiter is shedding load, when authentication middleware is failing. On its own listener it keeps answering, and it can be firewalled off from the internet.

health.WithHealthRouter(rx.RouterConfig{
	Addr:         "127.0.0.1:9091", // loopback only
	ReadTimeout:  5 * time.Second,
	MaxBodyBytes: 4 << 10,
})

To serve them on the application router instead:

health.WithAtDefaultAddr(true)

TLS on the health router is opt-in and configured like any other RouterConfig.

/live

{"status":"UP"}

Always 200 while the process is running. It runs no checks — that is the point.

A liveness probe answers "should this process be restarted?". Wiring dependency checks into it means a database outage restarts every replica, which turns a recoverable outage into a crash loop and puts the restarting replicas' own reconnection storm on top of it.

health.LiveHandler() returns it as a standalone http.Handler if you want it somewhere else.

/ready

{
  "status": "UP",
  "checks": {
    "database": {"status":"UP","duration":1200000,"timestamp":""},
    "cache":    {"status":"DEGRADED","message":"high latency","duration":}
  }
}

Runs the readiness checks only — those created with health.WithReadiness(true) — served from the snapshot cache (5s TTL by default).

200 unless the overall status is DOWN, in which case 503. A DEGRADED replica therefore keeps serving — degraded means "working, with problems".

A readiness probe answers "should traffic be routed here?". Failing it removes the replica from the load balancer without restarting it, which is the right response to a dependency outage.

Register as readiness only the dependencies without which this replica cannot usefully serve. A check on an optional cache should not remove the replica from rotation.

health.ReadyHandler(cache) is the standalone form.

/status

{
  "status": "DEGRADED",
  "timestamp": "2026-09-04T09:15:00Z",
  "checks": { "…": {"status":"UP", } },
  "dependencies": {
    "database": {
      "id": "database",
      "status": "UP",
      "last_check": "",
      "last_success": "",
      "failure_count": 0,
      "success_count": 1834,
      "last_latency": 1200000,
      "avg_latency": 1450000,
      "circuit_state": 0
    }
  }
}

Every check result and every dependency state, including latency statistics and circuit-breaker state. This is the operator view.

/status discloses your service topology. Dependency identifiers, failure counts and latencies are exactly what an attacker wants during an outage. Keep the health listener internal — bind it to loopback or a private interface, or put authentication in front of it if it must be reachable.

health.StatusHandler(cache, stateStore) is the standalone form.

Overall status

Snapshot.ComputeOverallStatus() reduces the individual results:

Any check Overall
all UP UP
at least one DEGRADED, none DOWN DEGRADED
at least one DOWN DOWN

Status.IsHealthy() is true for UP and DEGRADED — degraded means "working, with problems", not "broken".

Caching

/ready and /status are served from a snapshot refreshed at most every SnapshotTTL (5s default). Probes at 1-second intervals therefore do not execute checks 60 times a minute.

Lower it if you want probes to react faster; raise it if your checks are expensive. SnapshotCache.Invalidate() forces a refresh on the next read.

Probe configuration

livenessProbe:
  httpGet: { path: /live, port: 9091 }
  periodSeconds: 10
  failureThreshold: 3

readinessProbe:
  httpGet: { path: /ready, port: 9091 }
  periodSeconds: 5
  failureThreshold: 2

Note that /ready returns 200 for both UP and DEGRADED, so a degraded replica keeps serving. If you want degraded replicas out of rotation, gate at the route level instead — see The Dependency Gate.

Clone this wiki locally