Using Spring Boot Actuator Health Groups for Kubernetes Liveness and Readiness Probes
Configure Spring Boot Actuator health groups to provide distinct liveness and readiness signals for Kubernetes probes while protecting internal details.
27 Dec 2025, 03:58 UTC

Problem
When a Spring Boot service runs in Kubernetes, the pod must report two distinct signals: liveness (is the application still running) and readiness (can it serve traffic). If a downstream dependency such as a database or external API becomes unavailable, the service should stay alive (liveness UP) but be removed from the load balancer (readiness DOWN) so Kubernetes stops sending requests until the dependency recovers. Exposing too much detail in health responses can leak internal topology to unauthenticated callers.
Requirements
- Separate liveness and readiness endpoints that Kubernetes can query.
- Each critical downstream dependency represented by a Spring Boot
HealthIndicatorthat returns UP or DOWN with minimal detail. - Restrict health detail exposure to authorized callers only.
- Avoid health checks that perform heavy work or write operations.
Smallest suitable design
- Add
spring-boot-starter-actuatordependency. - In
application.properties(or YAML) enable the health endpoint and split groups:management.endpoints.web.exposure.include=health management.endpoint.health.group.liveness.include=livenessHealth management.endpoint.health.group.readiness.include=readinessHealth management.endpoint.health.show-details=when-authorized management.endpoint.health.group.liveness.show-details=never management.endpoint.health.group.readiness.show-details=when-authorized
- Define marker interfaces or annotations to assign indicators to each group. Spring Boot 3.x provides
org.springframework.boot.actuate.health.ReadinessHealthandorg.springframework.boot.actuate.health.LivenessHealthannotations:@Component @LivenessHealth public class DatabaseHealthIndicator implements HealthIndicator { @Override public Health health() { try { // lightweight connectivity test, e.g. SELECT 1 return Health.up().build(); } catch (Exception ex) { return Health.down(ex).build(); } } } @Component @ReadinessHealth public class ExternalApiHealthIndicator implements HealthIndicator { @Override public Health health() { try { // simple HTTP HEAD with short timeout return Health.up().build(); } catch (Exception ex) { return Health.down(ex).build(); } } } - Secure the actuator endpoint with Spring Security or rely on network policies so only the Kubernetes control plane and authorized internal services can reach
/actuator/health.
Trust and data boundaries
By default Actuator returns component names and details. Setting show-details=when-authorized hides them from anonymous requests. Combine with a security configuration that grants ROLE_ACTUATOR to the Kubernetes kubelet (via service account token) or to an internal monitoring service. Never return credentials, stack traces, or internal URLs in the health JSON.
Operational checks
- Measure round‑trip time of the health request; alert if it regularly exceeds 80 % of the Kubernetes probe timeout.
- Track the rate of DOWN responses; a sustained series should trigger an incident.
- Ensure each
HealthIndicatorperforms a non‑blocking, read‑only check (e.g., a lightweight query or a TCP socket connect with a short timeout). - Configure Kubernetes liveness probe to point to
/actuator/health/livenessand readiness to/actuator/health/readiness(or use the grouped paths).
Failure modes
- A blocking or slow
HealthIndicatoroccupies an actuator request thread, increasing latency and causing Kubernetes to mark the pod unhealthy even though the application is fine. - If readiness aggregates all indicators with an AND logic, a single flapping dependency can cause the pod to toggle readiness rapidly, leading to churn.
- Unauthenticated exposure of component names reveals the service’s dependency map, which could aid an attacker.
- When using a shared health indicator for multiple tenants, a failure in one tenant masks the health of others.
Conditions that change the design
- Multi‑tenant SaaS: expose a separate health endpoint per tenant or include tenant ID in the response after authentication.
- Need for non‑HTTP probes (TCP, gRPC): implement a custom actuator health endpoint that serves on a different port or use a sidecar that translates.
- Compliance regimes that forbid any detail: set
show-details=neverand rely solely on UP/DOWN status.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.