skip to content

What do /actuator/health and /actuator/info return, and where does their content come from?

level: juniorimportance: must knowfreq 60%

answer

  1. HealthEndpoint -> status UP/DOWN/OUT_OF_SERVICE/UNKNOWN
  2. HealthIndicator beans aggregated
  3. details hidden by default
  4. status -> HTTP 200/503 mapping
  5. info = InfoContributor: build-info + git.properties + info.*

basics

~20 s

/actuator/health reports whether the app and its dependencies are healthy, returning a status like UP or DOWN. /actuator/info returns arbitrary descriptive info (build version, git commit) contributed by the app; it is empty unless you configure contributors.

solid answer

~40 s

`/actuator/health` is backed by `HealthEndpoint`. It returns an overall `status` (`UP`, `DOWN`, `OUT_OF_SERVICE`, `UNKNOWN`) computed by aggregating every `HealthIndicator`/`HealthContributor` bean — e.g. `DataSourceHealthIndicator`, `DiskSpaceHealthIndicator`, `RedisHealthIndicator`. Per-indicator `details` are hidden by default and only shown when configured, so out of the box you typically just see `{"status":"UP"}`. The HTTP status code maps from the health status (200 for UP, 503 for DOWN by default), which is why load balancers and Kubernetes probes hit it. `/actuator/info` is backed by `InfoEndpoint` and aggregates `InfoContributor` beans; common sources are `build-info.properties` (Maven/Gradle build plugin), `git.properties` (git-commit plugin), and `management.info.*`/`info.*` properties. It's empty by default because no contributors produce data until you enable them.

code

java · 26 lines
java
// Custom HealthIndicator contributing to /actuator/health
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Component;

@Component
public class PaymentGatewayHealthIndicator implements HealthIndicator {
    private final PaymentGatewayClient client;

    public PaymentGatewayHealthIndicator(PaymentGatewayClient client) {
        this.client = client;
    }

    @Override
    public Health health() {
        try {
            client.ping();
            return Health.up().withDetail("gateway", "reachable").build();
        } catch (Exception ex) {
            // pushes the overall /actuator/health status toward DOWN
            return Health.down(ex).withDetail("gateway", "unreachable").build();
        }
    }
}
// The bean's id ('paymentGateway') becomes a key under health components
// when details are shown; its DOWN status can drive the aggregate to DOWN.

go deeper

for a junior

Know health reports UP/DOWN and info reports build/version data, and that info is empty unless configured.

for a middle

Explain HealthIndicator aggregation, the default hidden details, and the status→HTTP-code mapping used by probes.

for a senior

Discuss the contributor SPIs (HealthIndicator/InfoContributor) and the build/git plugin wiring behind info.

for a principal

Reason about probe reliability, why prod hides details, and version traceability via build-info in deployments.

These are the two most-used Actuator endpoints, especially in cloud/ops contexts. **`/actuator/health`.** Implemented by `HealthEndpoint`. Its job: answer 'is this application, and the things it depends on, working?' - The response has a top-level **`status`** which is one of four standard values defined by `Status`: **`UP`**, **`DOWN`**, **`OUT_OF_SERVICE`**, **`UNKNOWN`** (you can define custom ones). - The overall status is produced by aggregating individual **`HealthIndicator`** beans. A `HealthIndicator` is a bean with a `health()` method returning a `Health` object (status + optional details map). Spring Boot auto-configures many: `DiskSpaceHealthIndicator`, `DataSourceHealthIndicator` (runs a validation query), `RedisHealthIndicator`, `MongoHealthIndicator`, `RabbitHealthIndicator`, `PingHealthIndicator`, etc. — one is registered for most infrastructure on your classpath. - A **`StatusAggregator`** decides the overall status from the children (default: `DOWN` wins over `UP`). More on that at the composite/principal level. - **Details are hidden by default.** By default the endpoint shows only the aggregated `status`; per-indicator detail (disk free bytes, DB product name, etc.) requires `management.endpoint.health.show-details` to be raised (that property lives in the Boot-config leaf, but the *behavior* — no details unless allowed — is health-endpoint semantics you must know). So a default prod app returns simply `{"status":"UP"}`. - **HTTP status mapping.** A `HealthStatusHttpMapper`/`HttpCodeStatusMapper` maps the health status to an HTTP code: `UP` → 200, `DOWN`/`OUT_OF_SERVICE` → 503 by default, `UNKNOWN` → 200. This lets a load balancer or Kubernetes liveness/readiness probe treat a non-200 as unhealthy without parsing the body. **`/actuator/info`.** Implemented by `InfoEndpoint`. It returns a free-form JSON blob describing the app, aggregated from **`InfoContributor`** beans: - **`BuildInfoContributor`** reads `META-INF/build-info.properties`, generated by the Spring Boot **Maven/Gradle plugin** (`buildInfo` goal/task). Gives `build.version`, `build.artifact`, `build.time`, etc. - **`GitInfoContributor`** reads `git.properties` produced by the git-commit-id plugin — `git.branch`, `git.commit.id`, `git.commit.time`. - **`EnvironmentInfoContributor`** exposes any properties under the `info.` prefix from your configuration (e.g. `info.app.name=Foo`). - **`JavaInfoContributor`**, **`OsInfoContributor`** (opt-in via `management.info.java.enabled`/`os.enabled`). **Empty by default.** With no build/git plugin configured and no `info.*` properties, `/actuator/info` returns `{}`. That surprises people — it is not broken; there is simply nothing to contribute. **Gotchas.** - Seeing only `{"status":"UP"}` and concluding health checks are shallow: they aren't — the aggregation still ran across all indicators; you just aren't shown the breakdown unless details are enabled. - Expecting `/actuator/info` to auto-include version: it only does if the build plugin generated `build-info.properties`. - Confusing health *status* values with HTTP status *codes* — they are related but distinct (mapped by a mapper). - `health` is web-exposed by default; `info` is *not* web-exposed by default in current Boot versions, so you may need to expose it. **When to use.** `health` for liveness/readiness probes and LB checks; `info` for surfacing deployed version/commit so you can confirm what's actually running in an environment.

  • Why does /actuator/health often return just {"status":"UP"} with no breakdown?
    Per-indicator details are hidden by default; the endpoint only reveals the aggregated status unless `show-details` is raised (e.g. `when-authorized` or `always`). The indicators still ran; the detail is just not rendered.
  • How would you make the deployed version and git commit visible via /actuator/info?
    Enable the Spring Boot build plugin's build-info generation and the git-commit-id plugin so `build-info.properties` and `git.properties` are on the classpath; `BuildInfoContributor`/`GitInfoContributor` then populate the info response. Or add `info.*` properties.

saying these in an interview costs you the question

  • Claiming /actuator/health returns detailed component status by default
  • Assuming /actuator/info automatically shows the app version with no build plugin
  • Conflating the health Status value with the HTTP status code
  • Saying DOWN returns HTTP 200

context