This presentation covers the features and usage of Spring Boot Actuator.
Enabling Production-ready Features
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
access: /actuator endpoint
{
"_links": {
"self": {
"href": "http://localhost:8080/actuator",
"templated": false
},
"health-path": {
"href": "http://localhost:8080/actuator/health/{*path}",
"templated": true
},
"health": {
"href": "http://localhost:8080/actuator/health",
"templated": false
}
}
}
management:
endpoints:
web:
exposure:
include: "*"
Only expose what you really need!
By default, access to all endpoints except for
shutdownandheapdumpis unrestricted.
management:
endpoint:
shutdown:
access: unrestricted
heapdump:
access: unrestricted
Additional port for internal access
management:
server:
port: 8081
http :8081/actuator/health
Add Spring Security
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
management:
endpoint:
env:
show-values: when-authorized
spring:
security:
user:
name: admin
password: 123456
Stricter - Add Custom SecurityFilterChain
@Bean
SecurityFilterChain actuatorSecurityFilterChain(HttpSecurity http) throws Exception {
http
.securityMatcher(EndpointRequest.toAnyEndpoint())
.authorizeHttpRequests(requests -> requests
.requestMatchers(EndpointRequest.to("health", "info", "metrics", "prometheus")).permitAll()
.anyRequest().authenticated()
)
.httpBasic(Customizer.withDefaults())
.csrf(csrf -> csrf.disable());
return http.build();
}
Show Details
management:
endpoint:
health:
show-details: always
http :8081/actuator/health
{
"components": {
"diskSpace": {
"details": {
"exists": true,
"free": 870792753152,
"path": "/Users/matthew/projects/meirongdev/actuator-demo/.",
"threshold": 10485760,
"total": 994662584320
},
"status": "UP"
},
"ping": {
"status": "UP"
},
"ssl": {
"details": {
"invalidChains": [],
"validChains": []
},
"status": "UP"
}
},
"status": "UP"
}
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
Additional starters may add their own health indicators
output when redis is not available:
{
"components": {
"diskSpace": {
...
"status": "UP"
},
"ping": {
"status": "UP"
},
"redis": {
"details": {
"error": "org.springframework.data.redis.RedisConnectionFailureException: Unable to connect to Redis"
},
"status": "DOWN"
},
"ssl": {
"details": {
"invalidChains": [],
"validChains": []
},
"status": "UP"
}
},
"status": "DOWN"
}
Customize Health Indicator
@Bean(name = "depsIndicator")
HealthIndicator depsHealthIndicator() {
return () -> {
Health.Builder healthBuilder = Health.up();
// Define the services to check
Map<String, Boolean> serviceHealthMap = Map.of(
"serviceA", checkServiceA(),
"serviceB", checkServiceB()
);
// Check each service and update health status
serviceHealthMap.entrySet().forEach(entry -> {
if (!entry.getValue()) {
healthBuilder.down().withDetail(entry.getKey(), entry.getKey() + " is down");
} else {
healthBuilder.withDetail(entry.getKey(), entry.getKey() + " is healthy");
}
});
boolean allServicesHealthy = serviceHealthMap.values().stream()
.allMatch(Boolean::booleanValue);
return allServicesHealthy ? healthBuilder.build() : healthBuilder.down().build();
};
}
output in /actuator/health:
"depsIndicator": {
"details": {
"serviceA": "serviceA is healthy",
"serviceB": "serviceB is down"
},
"status": "DOWN"
},
Cache
management:
endpoint:
health:
cache:
time-to-live: 30s
Status Aggregation
management:
endpoint:
health:
status:
order: down, out-of-service, unknown, up
http-mapping:
down: 503
out-of-service: 503
unknown: 500
up: 200
Add custom http-mapping will remove default mapping.
management:
endpoint:
health:
probes:
enabled: true # This is enabled by default in k8s environment
add-additional-paths: true
group:
liveness:
include: diskSpace, ping
readiness:
include: db, redis # include all the indicators you want
Spring Boot auto-detects Kubernetes deployment environments by checking the environment for “_SERVICE_HOST” and “_SERVICE_PORT” variables.
You can override this detection with the spring.main.cloud-platform configuration property.
In the k8s side, can configure like this:
livenessProbe:
httpGet:
path: "/actuator/health/liveness"
port: <actuator-port>
failureThreshold: ...
periodSeconds: ...
readinessProbe:
httpGet:
path: "/actuator/health/readiness"
port: <actuator-port>
failureThreshold: ...
periodSeconds: ...
For the graceful shutdown, can refer to Spring Boot 3 Graceful Shutdown with Kubernetes.
Builtin contributors
Build Info
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<goals>
<goal>build-info</goal>
</goals>
</plugin>
<plugin>
<groupId>io.github.git-commit-id</groupId>
<artifactId>git-commit-id-maven-plugin</artifactId>
</plugin>
{
"git": {
"branch": "main",
"commit": {
"id": "f08b993",
"time": "2025-10-27T14:33:29Z"
}
}
}
Other Builtin Contributors
management:
info:
build:
enabled: true
git:
enabled: true
os:
enabled: true
process:
enabled: true
java:
enabled: true
ssl:
enabled: true
Write your own TBC
@Bean
InfoContributor barInfoContributor() {
return new InfoContributor() {
@Override
public void contribute(Info.Builder builder) {
builder.withDetail("bar", Map.of("now", Instant.now().toString()));
}
};
}