Health
Health probes answer the questions an orchestrator asks: should you
keep this pod running? should you route traffic to it? has it
finished booting? The probes ship as routes on the
HTTP transport. Importing HealthModule mounts three —
GET /health/live, GET /health/ready, GET /health/startup —
each returning 200 and a JSON body when every indicator passes,
503 with the same shape and error populated when any indicator
fails. Routing rides on poem (the
same engine HttpModule mounts), and discovery uses
inventory gated by the access
graph.
Install
Section titled “Install”cargo add nest-rs-healthMount it
Section titled “Mount it”use nest_rs_core::module;use nest_rs_health::HealthModule;
#[module(imports = [HealthModule])]pub struct ApiModule;Three routes appear at boot:
$ curl -s http://localhost:8080/health/live{"status":"up","info":{},"error":{},"details":{}}$ curl -s http://localhost:8080/health/ready{"status":"up","info":{},"error":{},"details":{}}$ curl -s http://localhost:8080/health/startup{"status":"up","info":{},"error":{},"details":{}}With no indicators registered every probe reports up with empty
buckets — useful for the first ten minutes; not for production. See
Indicators for the framework-shipped ones and
how to write your own.
The three probes
Section titled “The three probes”| Probe | Question the orchestrator asks | Default with no indicators |
|---|---|---|
live | Is the process still alive — should I restart it? | up |
ready | Should I send traffic to it right now? | up |
startup | Has it finished its long boot? | up |
The split mirrors the orchestrator’s: a long-booting app fails
startup until ready (so Kubernetes does not kill it for slow
liveness during boot); a temporarily overloaded app fails ready (so
traffic drains) without flagging live (the process is fine — do not
restart it).
The JSON shape
Section titled “The JSON shape”Every probe returns the same body. info holds the up indicators,
error holds the down ones, details carries the union so an
operator can grep one bucket without iterating a list.
$ curl -s http://localhost:8080/health/ready | jq{ "status": "up", "info": { "db": { "name": "db", "status": "up" }, "upstream": { "name": "upstream", "status": "up" } }, "error": {}, "details": { "db": { "name": "db", "status": "up" }, "upstream": { "name": "upstream", "status": "up" } }}When one indicator drops, the response moves to 503 and the
indicator migrates from info to error with its stringified cause:
$ curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8080/health/ready503$ curl -s http://localhost:8080/health/ready | jq{ "status": "down", "info": { "db": { "name": "db", "status": "up" } }, "error": { "upstream": { "name": "upstream", "status": "down", "error": "connection refused" } }, "details": { "db": { /* ... */ }, "upstream": { /* ... */ } }}The overall status is down if any indicator is down. The HTTP
status maps from that one bit: 200 for up, 503 for down.
Going further
Section titled “Going further”- Indicators — where they live, the
framework-shipped ones, writing a custom one with
#[indicators]. - Discovery — how module-gating decides which indicators run in a given binary.
- Database / Health —
DatabaseHealthModule, the first framework-shipped indicator. - HTTP — the transport
HealthModulemounts on; same#[controller]shape under the hood.