skip to content

What is the HttpCodeStatusMapper, and what HTTP status codes does /actuator/health return by default for each health status?

level: middleimportance: should knowfreq 50%

answer

  1. SimpleHttpCodeStatusMapper
  2. DOWN/OUT_OF_SERVICE → 503; UP/UNKNOWN → 200
  3. unmapped status → 200
  4. status.http-mapping.<status>=<code>
  5. probes/LB act on the code, not the body

basics

~10 s

The HttpCodeStatusMapper maps a health Status to an HTTP status code. By default DOWN and OUT_OF_SERVICE return 503 (Service Unavailable); UP and UNKNOWN return 200 OK. You customize it via management.endpoint.health.status.http-mapping.

solid answer

~30 s

After the StatusAggregator produces the overall Status, a HttpCodeStatusMapper (default SimpleHttpCodeStatusMapper) translates that Status into the HTTP status code of the /actuator/health response. Defaults: DOWN → 503, OUT_OF_SERVICE → 503, and everything else (UP, UNKNOWN, custom) → 200. This lets load balancers and Kubernetes probes act on the status code alone without parsing the body. You override the mapping with management.endpoint.health.status.http-mapping.<status>=<code>, e.g. map a custom FATAL to 503, or downgrade OUT_OF_SERVICE to 200. Note the status names in http-mapping are case-insensitive and any status without an explicit mapping defaults to 200.

code

yaml · 8 lines
yaml
management:
  endpoint:
    health:
      status:
        http-mapping:
          down: 503            # default, shown for clarity
          out-of-service: 200  # keep serving despite OOS
          fatal: 503           # map a custom status so probes react

go deeper

for a junior

Know DOWN → 503 and UP → 200.

for a middle

List all four default mappings and the http-mapping property.

for a senior

Explain the probe/LB rationale and the custom-status-defaults-to-200 gotcha.

for a principal

Reason about readiness vs liveness semantics and when to remap OUT_OF_SERVICE.

**Two separate concerns.** Aggregation decides *which* `Status` the endpoint reports (via `StatusAggregator`). The `HttpCodeStatusMapper` decides *what HTTP code* accompanies that status. They are configured independently. **SimpleHttpCodeStatusMapper.** The default mapper is `SimpleHttpCodeStatusMapper`. Its built-in mapping: - `DOWN` → **503** (Service Unavailable) - `OUT_OF_SERVICE` → **503** - `UP` → **200** (OK) - `UNKNOWN` → **200** - Any status with no explicit mapping → **200** **Why this matters.** Infrastructure health checks (AWS/GCP load balancers, Kubernetes `livenessProbe`/`readinessProbe`, HAProxy) typically make decisions on the **HTTP status code**, not the JSON body. So a `DOWN` overall status returning `503` lets a load balancer pull the instance out of rotation automatically, and a `readinessProbe` will stop routing traffic. If everything mapped to `200`, probes couldn't distinguish healthy from unhealthy without body parsing. **Customizing the mapping.** Use `management.endpoint.health.status.http-mapping.<status>=<code>`. Examples: ```yaml management.endpoint.health.status.http-mapping.down: 503 management.endpoint.health.status.http-mapping.out-of-service: 200 # keep serving management.endpoint.health.status.http-mapping.fatal: 503 # custom status ``` Status keys are **case-insensitive**, so `down`, `DOWN` both work, and `OUT_OF_SERVICE` can be written `out-of-service`. **Custom mapper bean.** For programmatic rules you can register your own `HttpCodeStatusMapper` bean, replacing `SimpleHttpCodeStatusMapper`. Rarely necessary. **Gotchas.** - **Custom statuses default to 200.** If you introduce `Status("FATAL")` and want probes to react, you must add an http-mapping for it — otherwise it silently returns 200 even though the body says FATAL. - **The mapping applies to the *aggregate* status,** not per component. A component being DOWN only yields 503 if it makes the *overall* status DOWN (which by default it does). - **Don't confuse `status.http-mapping` with `status.order`** — order affects which status wins; http-mapping affects the returned code. - The mapper only affects the health endpoint response code; it does not change the aggregated `Status` value in the body.

  • A Kubernetes readinessProbe hits /actuator/health and the overall status is OUT_OF_SERVICE. What happens by default?
    OUT_OF_SERVICE maps to 503 by default, so the probe fails and Kubernetes stops routing traffic to the pod until it returns 200.
  • You added a custom FATAL status; the body shows FATAL but the response is still 200. Why?
    Statuses without an explicit http-mapping default to 200. Add management.endpoint.health.status.http-mapping.fatal=503 so it returns 503.

saying these in an interview costs you the question

  • Claiming DOWN returns HTTP 500 (it's 503)
  • Thinking UNKNOWN returns 503 (it returns 200 by default)
  • Assuming custom statuses automatically map to 503

context