WSS
On this page
Monitoring & ObservabilityRequiredUpdated

Health Check Response Format (RFC)

The IETF standard (RFC 9474) defining a consistent, machine-readable JSON schema for APIs and microservices to report their health status to orchestrators.

What it is

In distributed systems, load balancers and orchestrators (like Kubernetes) continuously ping services to ask, “Are you healthy?” Historically, every engineering team invented their own way to answer this question. Some teams returned an HTTP 200 OK with the text “OK”. Others returned a complex JSON object like {"database": true, "cache": false}.

This lack of standardization meant that external monitoring tools could not easily parse why a service was failing without custom-coded adapters for every single microservice.

RFC 9474 provides a formalized JSON schema. It establishes a universal vocabulary for a service to declare its overall status (pass, fail, or warn) alongside granular, component-level details about its underlying dependencies.

Why it matters

When an application crashes, the orchestrator needs to know immediately so it can kill the container and route traffic elsewhere.

However, if an application relies on a third-party billing API, and that external API goes down, the application itself hasn’t crashed. Should the application report that it is “unhealthy” and let Kubernetes kill it? No, because killing the container won’t fix the third-party billing API.

The RFC 9474 format allows a service to communicate nuance. It can report an overall status of warn (indicating degraded performance) while explicitly listing the billing API as the exact component causing the failure. This prevents orchestrators from blindly destroying healthy containers, while simultaneously providing SREs with instantaneous root-cause diagnostics.

How to implement

The RFC specifies the application/health+json MIME type. The HTTP status code dictates the high-level routing decision, while the JSON body provides the diagnostic details.

Status Codes

  • 2xx (Usually 200 OK): The service is healthy.
  • 4xx or 5xx (Usually 503 Service Unavailable): The service is unhealthy and should be removed from the load balancer pool.

The JSON Schema

The top-level status field is required. It must be pass, fail, or warn. The checks object is optional but highly recommended; it details the health of downstream dependencies.

{
  "status": "fail",
  "version": "1.4.2",
  "releaseId": "abc123z",
  "notes": ["Upstream dependencies are failing"],
  "output": "Database connection timeout",
  "checks": {
    "primary:database": [
      {
        "status": "fail",
        "time": "2026-07-31T14:22:00Z",
        "output": "Connection refused on port 5432"
      }
    ],
    "cache:redis": [
      {
        "status": "pass",
        "time": "2026-07-31T14:22:00Z"
      }
    ]
  }
}

Common mistakes

Exposing Sensitive Data

Because health checks are often exposed on unauthenticated endpoints (so the load balancer can reach them easily), dumping raw stack traces or database connection strings into the output field is a critical security vulnerability. The JSON response must only contain safe, generic error identifiers, not PII or internal credentials.

The Cascading Failure Trap

If Service A checks the health of Service B, and Service B checks the health of Service C, a failure in C will cause B to report fail, which causes A to report fail. The load balancer sees A is failing and terminates it, even though A is perfectly fine and just waiting on C. Health checks should generally be “shallow” - reporting the health of the local process, not recursively querying the entire architecture. If deep dependency checks are used, they should result in a warn status, not a fail status, to prevent cascading orchestrator evictions.

Ignoring Content Negotiation

Strictly compliant clients will request the health check using an Accept: application/health+json header. If a framework’s default router intercepts this and attempts to serve HTML or raw text instead of the required JSON schema, the monitoring client will fail to parse the response.

Verification

To verify compliance with the RFC, query the application’s health endpoint and inspect both the HTTP status code and the Content-Type.

curl -i -H "Accept: application/health+json" http://localhost:8080/health

Expected Output:

HTTP/1.1 200 OK
Content-Type: application/health+json; charset=utf-8

{
  "status": "pass",
  "checks": {
    "database": [{"status": "pass"}]
  }
}

Related topics

Sources & further reading