Separate required readiness from optional capabilities
A live process, a service ready for its critical path, and a service with every optional feature working are different facts. Putting them into one ready value can turn an optional model outage into a full restart, whil…
Table of contents
A live process, a service ready for its critical path, and a service with every optional feature working are different facts. Putting them into one ready value can turn an optional model outage into a full restart, while liveness hides a critical database outage.
Three states
liveness: can the process receive requests?readiness: can it safely serve the product's required path?capability: is one database, model, push path, or scheduler working now?
The Python search backend keeps /health/ready focused on two required search gates: its database and embedding model. /health/capabilities reports domain databases, text and vision models, push, and the scheduler independently. When an optional capability is down but required gates are healthy, it returns HTTP 200 with degraded: true.
Keep the response safe
Return only the minimum operational fields such as ok, reachable, configured, model_loaded, running, and job_count. Health responses must not contain DSNs, internal endpoints, tokens, provider error bodies, or user text. Wrap slow database and model probes in a thread pool with a timeout so the event loop stays responsive.
What it means for operators and users
Operators should restore the required search path when the result is not_ready, and inspect only the affected optional feature when the result is ready + degraded. User interfaces should show the error, retry, or fallback action for the feature being used instead of waiting for every capability to be green. A single health number is not product success; record impact scope and recovery ownership with the status.
State decision matrix
| Liveness | Readiness | Capability | Platform action | User impact |
|---|---|---|---|---|
| Failed | Not evaluated | Not evaluated | Restart process | Full outage |
| Healthy | Failed | Some/all failed | Remove from traffic | Core path unavailable |
| Healthy | Ready | Some failed | Do not restart | Degrade only that feature |
| Healthy | Ready | Healthy | Serve normally | None |
{"ready":true,"degraded":true,"capabilities":{"database":"ok","vision":"disabled"}}
Separate an intentionally disabled capability from a failed one. Alerting on a cost-gated model as if it were broken can cause operators to start unnecessary instances and create fixed cost.
Related course: Operating Compose, readiness, reverse proxy, and rollback