Files
spring-boot-demo/README.md
Ankur Mhatre 4b6cefa60a Spring Boot 4 Actuator in production: endpoints, security, custom health indicators
Companion repository for the ankurm.com article. Every transcript in docs/output/
was produced by running this project; scripts/run-all.sh regenerates all of them.

Verified against Spring Boot 4.1.1 / Framework 7.0.9 / Security 7.1.1 /
Micrometer 1.17.1 / kafka-clients 4.2.1 on Temurin JDK 25.0.4.1+1.
2026-09-04 10:40:04 +05:30

7.5 KiB
Executable File

spring-boot-demo — Actuator in production

Companion repository for Spring Boot Actuator in Production on ankurm.com.

Every status code, JSON body, byte count and timing figure in the article was produced by running this project. The transcripts live in docs/output/ and are regenerated by a single command.


Versions

Verified with mvn dependency:list on the machine that produced docs/output/ — see docs/output/00-versions.txt.

Component Version Notes
Spring Boot 4.1.1 GA 20 August 2026
Spring Framework 7.0.9 via spring-boot-starter-parent
Spring Security 7.1.1 via spring-boot-starter-parent
spring-boot-actuator 4.1.1
spring-boot-health 4.1.1 new module in Boot 4HealthIndicator lives here now
spring-boot-restclient 4.1.1 not pulled in by the web starter
Micrometer 1.17.1 there is no Micrometer 2.x GA; see docs/02
kafka-clients 4.2.1 what Boot 4.1.1 manages (4.3.1 is the latest on Central)
H2 2.4.240
JDK Temurin 25.0.4.1+1 LTS
Maven 3.9.11

Quickstart

export JAVA_HOME=/path/to/jdk-25
mvn -DskipTests package

# defaults: only /actuator/health is exposed
java -jar target/actuator-production-1.0.0.jar

# every endpoint, no authentication - the configuration you should never ship
java -jar target/actuator-production-1.0.0.jar --spring.profiles.active=exposeall,open

# the configuration you should ship
java -jar target/actuator-production-1.0.0.jar --spring.profiles.active=secured

Credentials for every profile that requires them: ops / ops-password.

Regenerate every transcript in docs/output/:

JAVA_HOME=/path/to/jdk-25 ./scripts/run-all.sh

That takes roughly three minutes, most of which is the naive Kafka scenario blocking for its full 60 seconds. That is the point of it.


Profiles

Profile What it demonstrates
(none) Boot defaults. Only health on the web, show-details: never
exposeall management.endpoints.web.exposure.include: "*"
open A permitAll security chain — the misconfiguration, kept on purpose
secured EndpointRequest.toAnyEndpoint() + ROLE_ACTUATOR + when-authorized details
mgmtport Actuator on port 9001, base path /manage, bound to loopback
details show-details: always — the full component breakdown
groups liveness / readiness / startup groups wired correctly
kafkanaive The textbook AdminClient health check, so its 60-second block can be timed

Profiles compose: --spring.profiles.active=exposeall,open.


Endpoints

Read from the running application, not from the documentation — see docs/output/02-endpoint-catalogue.txt.

Endpoint Web-exposed by default access default Notes
health yes unrestricted the only one exposed out of the box
info no unrestricted Boot 4.1 added process.* fields
beans no unrestricted 426 beans in this app, with types and wiring
conditions no unrestricted the auto-configuration report
configprops no unrestricted values masked like env
env no unrestricted masks every value unless show-values says otherwise
loggers no unrestricted has a POST — a write endpoint
mappings no unrestricted every URL your app serves
metrics no unrestricted from spring-boot-micrometer-metrics
prometheus no unrestricted needs micrometer-registry-prometheus
sbom no unrestricted
scheduledtasks no unrestricted
threaddump no unrestricted two operations: JSON and text/plain
heapdump no none include: "*" is not enough
shutdown no none include: "*" is not enough
startup no unrestricted needs a BufferingApplicationStartup
httpexchanges no unrestricted needs an HttpExchangeRepository bean
auditevents no unrestricted needs an AuditEventRepository bean
logfile no unrestricted needs logging.file.name
caches, flyway, liquibase, quartz, sessions, integrationgraph no unrestricted conditional on the relevant module
diag no unrestricted this repository's own — delete before shipping

heapdump and shutdown are the only two endpoints whose access defaults to none. That list came from Spring Boot's own spring-configuration-metadata.json, not from a blog.


Documentation

# Chapter
01 What Actuator actually exposes
02 What changed in Spring Boot 4
03 The endpoint catalogue
04 Securing Actuator
05 Custom health indicators
06 Health indicator failure modes
07 Groups, probes and Kubernetes
08 The diagnostics endpoint
09 Testing Actuator

Captured output

File Scenario
00-versions.txt resolved dependency versions
01-default-exposure.txt Actuator with zero configuration
02-endpoint-catalogue.txt every exposed endpoint, from the running app
03-open-actuator-leak.txt what an anonymous caller really gets
04-heapdump-leak.txt 59 MB, plaintext credentials inside
05-secured-matrix.txt the full authorisation matrix
06-management-port.txt port 9001, and what it isolates
07-custom-health-indicators.txt DB, Kafka and external API
08-groups-and-probes.txt liveness 200 while readiness 503
09-kafka-timeout.txt.tuned 1.6 s
09-kafka-timeout.txt.naive 60.2 s
10-slow-upstream.txt a read timeout doing its job

Status codes and bodies are reproducible. Timing figures are indicative and drift between machines — except the 60-second one, which is a Kafka default and lands on 60.0 s every time.


Layout

pom.xml
scripts/
  run-all.sh                regenerate everything below docs/output/
  run.sh / stop.sh          start and stop with given profiles
  demo-*.sh                 one script per captured scenario
src/main/java/com/ankurm/actuator/
  health/                   OrdersDatabase, Kafka, ExternalApi indicators + UpstreamState
  config/                   Secured, Open and baseline security chains
  web/                      DiagnosticsEndpoint, stub upstream, business controller
src/test/java/              contract tests for the surprising behaviour
docs/                       numbered chapters
docs/output/                captured real output

Licence

MIT — see LICENSE.