Health and status contract¶
Health endpoints are routinely misread. A service that answers 200 OK on a
liveness probe is frequently assumed to be working, when all it has demonstrated
is that a process is running and a socket is accepting connections.
ONIX separates those meanings deliberately. This page documents the public half of that model. The operational half — thresholds, monitors, notification handling and escalation — is internal and deliberately not published; see the documentation model.
Two generations, two different shapes¶
The backend serves two API generations side by side, and their health surfaces do not have the same shape. Treating them as one contract with a different prefix is the most common way to misread either.
| v1 | v2 | |
|---|---|---|
| Liveness | /health |
/v2/health |
| Condition and freshness | /readiness |
/v2/status |
A /readiness sibling |
yes | no — /v2/readiness is not a defined route |
| Implementation | python/src/onix_engine/gateway.py |
python/src/onix_engine/spine/gateway_v2.py |
Two consequences follow, and both matter.
There is no /v2/readiness. A client that constructs one by analogy with v1
is asking for a route the backend does not define. The generated
API and schema navigation lists the v2 route table exactly as
the backend declares it.
/v2/health is not the v2 spelling of /health. The v2 health document
already carries readiness and degradation facts. Reading it as a socket-liveness
ping understates what it reports and throws away the part a caller most needs. In
v1 those facts live one route away, on /readiness.
The three questions¶
Underneath the two generations there are still three distinct questions, and the value of any health model is in refusing to merge them.
| Question | v1 surface | v2 surface | Answers | Does not answer |
|---|---|---|---|---|
| Is the process alive? | /health |
part of /v2/health |
A process exists and its transport responds. | Whether it can do useful work. |
| Is it ready to serve? | /readiness |
part of /v2/health |
Lifecycle state, plus data-quality counters such as gaps, duplicates and out-of-order arrivals. | Whether the answers it gives are correct, or whether upstream venues are healthy. |
| What is it actually doing? | — | /v2/status |
Runtime counters, rates, watermarks and catalog state. | Anything about a different node or a different deployment. |
The important line is between the first and the second. Liveness does not imply readiness. A live process with an unhydrated catalog or a stalled subscription is live and not ready, and the model reports exactly that rather than collapsing both into a single green light.
Availability is a third thing, and it is per node¶
Health tells you how a node is doing. It does not tell you which operations that node offers at all. Those are separate questions with separate answers, and the backend keeps them separate:
- 404
NOT_SUPPORTED_ON_THIS_NODE— this node has no concept of that operation. Waiting will not help. - 501
CAPABILITY_DEFERRED— this node understands the operation and this release deliberately does not serve it.
Ten operations are deferred at the reviewed pin, covering the account, portfolio, order, fill and position read surface and the whole sandbox lifecycle. They are deferred on the nodes that defer them, not build-wide: a node that runs an execution client serves the same read surface through the same handlers and reports it ready. There is no build-wide deferred list a client may hard-code.
Read availability from the node you are talking to, through its own capability registry. The API and schema navigation page lists which operations are deferred and quotes the backend's own reason for each.
Why data-quality counters belong in readiness¶
Readiness in a market-data system is not a boolean about process state; it is a statement about whether the data plane is currently trustworthy. Gap, duplicate and out-of-order counters are therefore part of the readiness surface rather than a separate metrics concern.
This is a direct consequence of the absence-is-a-value principle: a component that cannot currently be trusted must say so, rather than serving plausible output and letting a consumer discover the problem later.
See ingestion and coverage for what the counters count, and the catalog for hydration state.
Scope limits you must respect¶
A health surface describes one node. It says nothing about a sibling node, a different shard, or the deployment as a whole. Aggregating several nodes' health into a single system verdict is an operational concern and is not part of this public contract.
A health surface describes now. It is not a history, an audit trail or an availability record. Nothing on it is a commitment about future availability.
A health surface is not an entitlement check. Readiness says the system can serve; it says nothing about whether a particular caller is permitted to be served. Identity and access control are not documented as complete on this site; see support and scope.
Absence of an error is not evidence of correctness. The counters report detected problems. Undetected problems are, by construction, not represented.
How to read a health answer responsibly¶
- Read liveness only as "the process exists".
- Read readiness as a data-quality statement, and read the counters, not just the verdict.
- Read status counters as instantaneous, node-local and unaudited.
- Do not infer deployment composition from health. What is deployed is a separate question with a separate, weaker kind of evidence; see runtime and deployment.
What is deliberately withheld¶
The following existed in the documentation set this site replaces and is quarantined rather than published: monitor inventories, alert thresholds, notification routing, critical-alerting procedure, deployment and recovery runbooks, and incident history. These expose private topology and internal response process, and provide no benefit to a reader of public documentation.
The fact of their withholding is recorded openly in the quarantine register.
Evidence and source pins for this page
Verified. Current behaviour, confirmed in source at the pinned commit.
Verified on against the following immutable sources:
backend:python/src/onix_engine/gateway.py#blob=c470c9425035c038384bf37fa8eaa7447a838d81backend:python/src/onix_engine/spine/gateway_v2.py#blob=496e140b03f6885c3f4e5edeff28da9a2a36178fbackend:python/src/onix_engine/spine/deferred.py#blob=9e7124febde2b3054ad97c1cea5d1d733a377a06onix-docs:manifest/api-surface.json
Status tokens are defined on the documentation and status model page. Every pin on this site is listed under versions and source pins.