What is the HttpCodeStatusMapper, and what HTTP status codes does /actuator/health return by default for each health status?
answer
- SimpleHttpCodeStatusMapper
- DOWN/OUT_OF_SERVICE → 503; UP/UNKNOWN → 200
- unmapped status → 200
- status.http-mapping.<status>=<code>
- probes/LB act on the code, not the body
basics
~10 sThe 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 sAfter 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 linesmanagement:
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 reactgo deeper
Know DOWN → 503 and UP → 200.
List all four default mappings and the http-mapping property.
Explain the probe/LB rationale and the custom-status-defaults-to-200 gotcha.
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