Skip to content

Spring Boot 4 Health Indicator Changes: New HealthContributor API

I spent a whole afternoon trying to figure out why my custom health indicator stopped working after upgrading to Spring Boot 4. The actuator endpoint was returning nothing for my carefully crafted health checks. After digging through the API documentation, I realized the entire health indicator system got a major overhaul.

Here’s what I found and how I fixed it.

What Changed in Spring Boot 4

The health indicator system in Spring Boot 4 introduces a new hierarchy. Instead of just implementing HealthIndicator, you now have a more flexible structure:

HealthContributor (sealed interface)
├── HealthIndicator (for single checks)
└── CompositeHealthContributor (for grouping multiple checks)

The key difference is that Spring Boot 4 now requires HealthContributorAutoConfiguration, which only works with Spring Boot 4.0.0+. If you’re on an earlier version, your custom health indicators might not register properly.

My Migration Journey

I had a simple health indicator in Spring Boot 3.x:

@Component
public class CustomHealthIndicator implements HealthIndicator {
@Override
public Health health() {
return Health.up()
.withDetail("service", "running")
.build();
}
}

After upgrading to Spring Boot 4, this still technically works because HealthIndicator extends HealthContributor. But I wanted to take advantage of the new composite features.

Using CompositeHealthContributor

Here’s how I built a composite health contributor that groups multiple checks together:

@Component
public class CompositeHealthContributorExample implements CompositeHealthContributor {
private final Map<String, HealthContributor> contributors = new HashMap<>();
public CompositeHealthContributorExample() {
contributors.put("db", new DatabaseHealthIndicator());
contributors.put("redis", new RedisHealthIndicator());
}
@Override
public Iterator<NamedHealthContributor> iterator() {
return contributors.entrySet().stream()
.map(e -> NamedHealthContributor.of(e.getKey(), e.getValue()))
.iterator();
}
@Override
public HealthContributor getContributor(String name) {
return contributors.get(name);
}
}

This gives you a clean way to organize related health checks under a single parent in the /actuator/health endpoint.

Why This Matters

The new structure makes sense when you think about it. Single health indicators are simple - they just return UP or DOWN. But real applications often have complex health dependencies. The composite approach lets you:

  1. Group related checks (database, cache, external services)
  2. See the full health tree in one endpoint response
  3. Add new checks without modifying existing code

Common Pitfalls

Two things caught me out during migration:

  1. AutoConfiguration version requirement - HealthContributorAutoConfiguration explicitly requires Spring Boot 4.0.0+. Don’t expect it to work in earlier versions even if you manually register beans.

  2. Interface hierarchy - HealthIndicator now extends HealthContributor. Your existing implementations will still work, but new code should be aware of the composite option.

The Fix

If your health indicators aren’t showing up after upgrading, make sure:

  • You’re on Spring Boot 4.0.0 or higher
  • Your custom indicators implement the correct interface
  • The actuator endpoint is properly configured

The migration isn’t painful - it’s mostly backward compatible. But understanding the new hierarchy helps you leverage the composite features if you need them.

Final Words + More Resources

My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!

Comments