ARTICLE AD BOX
I have a Spring Boot application running in Kubernetes. I’m trying to implement a graceful shutdown flow using a readiness probe:
App receives SIGTERM.
App should start returning 503 from /health so Kubernetes stops sending new traffic.
Existing requests finish.
App shuts down.
I’d like to record metrics for the last few /health calls (especially the 503 responses during shutdown) using Micrometer’s MeterRegistry. However, I’m seeing that the MeterRegistry is already closed while the readiness probe is still hitting /health.
Relevant k8s config:
readinessProbe: initialDelaySeconds: 30 periodSeconds: 1 failureThreshold: 1 httpGet: path: /health port: 9091Controller:
import io.micrometer.core.instrument.MeterRegistry; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import static org.springframework.http.HttpStatus.SERVICE_UNAVAILABLE; @RestController @RequiredArgsConstructor @Slf4j public class HealthController { private final StatusService statusService; private final MeterRegistry meterRegistry; @GetMapping("/health") public ResponseEntity<String> health() { Status status = statusService.status(); ResponseEntity<String> response = status == Status.OK ? ResponseEntity.ok(status.name()) : ResponseEntity.status(SERVICE_UNAVAILABLE).body(status.name()); int statusCode = response.getStatusCode().value(); String statusCodeString = String.valueOf(statusCode); meterRegistry.counter("health_check_status", "code", statusCodeString).increment(); log.debug("Health check returned: {}. Status code: {}. meterRegistry.isClosed(): {}", response, statusCodeString, meterRegistry.isClosed()); return response; } }Logs around shutdown:
2025-12-08 13:15:24.096 Health check returned: <200 OK OK,OK,[]>. Status code: 200. meterRegistry.isClosed(): false 2025-12-08 13:15:25.092 Health check returned: <200 OK OK,OK,[]>. Status code: 200. meterRegistry.isClosed(): false 2025-12-08 13:15:26.092 Health check returned: <503 SERVICE_UNAVAILABLE Service Unavailable,SHUTTING_DOWN,[]>. Status code: 503. meterRegistry.isClosed(): true 2025-12-08 13:15:26.095 Health check returned: <503 SERVICE_UNAVAILABLE Service Unavailable,SHUTTING_DOWN,[]>. Status code: 503. meterRegistry.isClosed(): trueSo when my StatusService reports SHUTTING_DOWN and /health starts returning 503, meterRegistry.isClosed() is already true, which means I can’t reliably record those 503 metrics.
From what I can see:
MeterRegistry is created and managed by Spring Boot auto-configuration.
On SIGTERM, Spring Boot shuts down and eventually calls MeterRegistry#close().
I don’t directly control the registry bean (no custom bean definition, no @DependsOn, etc.).
Questions
Is there a way in Spring Boot to delay or customize when MeterRegistry.close() is called during shutdown, so that I can still write metrics during the last readiness probe calls?
If not, what is the recommended pattern to:
Keep /health responding with accurate status during shutdown, and
Still record metrics for those responses, when MeterRegistry is managed by Spring Boot?
