skip to content

Explain the difference between an endpoint being enabled and being exposed. Why does an endpoint need both?

level: middleimportance: should knowfreq 55%

answer

  1. enabled = bean exists
  2. exposed = reachable over transport
  3. reachable = enabled AND exposed
  4. shutdown disabled by default
  5. `*` spans only enabled endpoints

basics

~20 s

Enabled means the endpoint bean is active and can do its work; exposed means it's reachable over a technology (web/JMX). An endpoint must be both to be callable. Most are enabled by default; only health is web-exposed by default.

solid answer

~40 s

Actuator has two orthogonal gates. **Enablement** (`management.endpoint.<id>.enabled`, or global `management.endpoints.enabled-by-default`) decides whether the endpoint exists as an active bean at all. **Exposure** (`management.endpoints.web|jmx.exposure.include/exclude`) decides whether an enabled endpoint is reachable over that transport. An endpoint is invocable only when it is BOTH enabled AND exposed. Almost every built-in endpoint is enabled by default; `shutdown` is the exception (disabled). Exposure defaults are stingy: only `health` over the web. The practical consequence: `include=*` won't surface `shutdown` (it's disabled), and enabling `metrics` doesn't make it web-reachable unless it's also in the include set. Disabling an endpoint removes it entirely — its auto-configuration is skipped, which also frees resources; excluding it from exposure just hides that transport.

code

java · 9 lines
java
// Lock everything down, then opt in explicitly:
management.endpoints.enabled-by-default=false        // gate 1: nothing enabled
management.endpoint.health.enabled=true              // enable health
management.endpoint.info.enabled=true                // enable info
management.endpoints.web.exposure.include=health,info// gate 2: expose them over HTTP

// Enabling shutdown is required before '*' can ever expose it:
management.endpoint.shutdown.enabled=true
management.endpoints.web.exposure.include=*          // now includes shutdown too

go deeper

for a junior

May conflate the two switches; should at least recall both exist.

for a middle

Must state the AND rule and the shutdown default clearly.

for a senior

Uses enabled-by-default=false lock-down and reasons about cost vs transport separation.

for a principal

Designs a defense-in-depth default (disabled+unexposed baseline) as a platform standard across services.

## Two independent gates Actuator reachability is an **AND** of two separate switches: ### 1. Enablement - Per-endpoint: `management.endpoint.<id>.enabled=true|false` (e.g. `management.endpoint.shutdown.enabled=true`). - Global default: `management.endpoints.enabled-by-default=true|false` sets the baseline for all endpoints; per-endpoint properties override it. - A **disabled** endpoint is not created — its bean and auto-configuration are skipped, so it consumes no resources and cannot be exposed by any technology, wildcard or not. - Default: **all built-in endpoints are enabled except `shutdown`.** ### 2. Exposure - Per technology: `management.endpoints.web.exposure.include/exclude` and `management.endpoints.jmx.exposure.include/exclude`. - Controls whether an already-**enabled** endpoint is reachable over web and/or JMX. - Default: **web exposes only `health`**; JMX is off by default in modern Spring Boot. ## The AND rule An endpoint is callable over a transport only when it is **enabled AND exposed** on that transport. Truth table for the web: | Enabled? | In web include (minus exclude)? | Reachable over HTTP? | |---|---|---| | yes | yes | ✅ | | yes | no | ❌ (404) | | no | yes | ❌ (not even created) | | no | no | ❌ | ## Why two switches? - **Enablement** is about *existence and cost* — turning off `heapdump` or `threaddump` removes capability entirely. Turning off everything except what you use (`enabled-by-default=false` + selectively enable) shrinks both attack surface and startup cost. - **Exposure** is about *transport reachability* — the same enabled endpoint can be JMX-only (for internal tooling) yet hidden from HTTP. ## Consequences and gotchas - `management.endpoints.web.exposure.include=*` does **not** expose `shutdown`, because `shutdown` is disabled by default and `*` only spans enabled endpoints. To expose it: `management.endpoint.shutdown.enabled=true` (then `*` covers it) — and be very careful, it stops the app. - Enabling an endpoint does not web-expose it; you still need it in the include set. - Disabling via `enabled=false` cannot be overridden by exposure — exposure never resurrects a disabled endpoint. - Locking down with `enabled-by-default=false` is the strongest posture: nothing exists unless explicitly re-enabled.

  • How do you make `shutdown` callable over HTTP?
    Enable it (`management.endpoint.shutdown.enabled=true`) AND expose it (`...web.exposure.include=shutdown` or `*`). Both gates are required; enabling alone isn't enough.
  • What's the tightest lock-down posture?
    `management.endpoints.enabled-by-default=false`, then selectively enable and expose only what you need — disabled endpoints aren't even created, so exposure can't surface them.

saying these in an interview costs you the question

  • Thinking exposure can make a disabled endpoint reachable
  • Believing enabling an endpoint automatically exposes it over HTTP
  • Assuming `include=*` surfaces shutdown

context