Why Custom Health Indicators?
Spring Boot provides several built-in health checks (e.g., diskSpace, db, ping), but what if:
- Your system depends on a third-party API, and if that service is down, your app is practically unusable?
- You need to verify if a certain table in your database has expected values?
- You want to check if a certificate is valid or a cache is filled?
This is where custom health indicators come into play.
How to Create a Custom Health Indicator?
You can create a custom health indicator by doing one of the following:
Option 1: Implement HealthIndicator Interface
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Component;
@Component
public class MyApiHealthIndicator implements HealthIndicator {
@Override
public Health health() {
// Simulate a failing check
boolean apiIsDown = true;
if (apiIsDown) {
return Health.down()
.withDetail("API Status", "External API is down")
.withDetail("Reason", "SSL Certificate expired")
.build();
}
return Health.up()
.withDetail("API Status", "Running smoothly")
.build();
}
}
Option 2: Extend AbstractHealthIndicator
import org.springframework.boot.actuate.health.AbstractHealthIndicator;
import org.springframework.boot.actuate.health.Health;
import org.springframework.stereotype.Component;
@Component
public class ExternalServiceHealthIndicator extends AbstractHealthIndicator {
@Override
protected void doHealthCheck(Health.Builder builder) throws Exception {
// Custom logic
boolean serviceIsOk = true;
if (serviceIsOk) {
builder.up().withDetail("External Service", "Available");
} else {
builder.down().withDetail("External Service", "Unavailable");
}
}
}
Both classes must be annotated with @Component so Spring can detect and register them as beans.
What Happens Internally?
When Spring Boot sees a bean of type HealthIndicator, it automatically aggregates it into the /actuator/health endpoint.
By default, the overall health status is composite, meaning:
- If all indicators return
UP, the status isUP. - If any returns
DOWN, the overall status isDOWN. - Some statuses like
UNKNOWNdo not affect the overall health.
Testing the Custom Indicator
Once your custom indicator is added, start your app and hit:
GET https://localhost:8080/actuator/health
Example Response
{
"status": "DOWN",
"components": {
"db": { "status": "UP" },
"diskSpace": { "status": "UP" },
"ping": { "status": "UP" },
"myApiHealthIndicator": {
"status": "DOWN",
"details": {
"API Status": "External API is down",
"Reason": "SSL Certificate expired"
}
}
}
}
As you can see, one failing component (myApiHealthIndicator) caused the overall health to become DOWN.
