Spring Boot cookbook · Intermediate

Shut down Spring Boot gracefully on Kubernetes

Deploy new versions without dropping in-flight requests or failing health checks.

Approach

Enable graceful shutdown (default in recent Boot versions) with a timeout, expose liveness/readiness probes, and add a short preStop sleep so the pod is removed from Service endpoints before Tomcat stops accepting connections. Keep terminationGracePeriodSeconds longer than preStop + shutdown timeout.

Solution

# application.yml
server:
  shutdown: graceful
spring:
  lifecycle:
    timeout-per-shutdown-phase: 25s
management:
  endpoint:
    health:
      probes:
        enabled: true
# deployment.yaml (excerpt)
spec:
  terminationGracePeriodSeconds: 45
  containers:
    - name: api
      image: registry.example.com/shop-api:1.42.0
      readinessProbe:
        httpGet: { path: /actuator/health/readiness, port: 8081 }
        periodSeconds: 5
      livenessProbe:
        httpGet: { path: /actuator/health/liveness, port: 8081 }
        periodSeconds: 10
      lifecycle:
        preStop:
          exec: { command: ["sh", "-c", "sleep 10"] }

Pitfalls

  • No preStop delay: endpoints update after the app already stopped accepting connections (502s).
  • Grace period shorter than shutdown timeout (SIGKILL mid-request).
  • Liveness probes on external dependencies.

Variations

  • Distroless images without sh: use a sleep binary or preStop.sleep (Kubernetes 1.30+).

Further reading: Spring Boot: Graceful shutdown

Reference: https://docs.spring.io/spring-boot/reference/web/graceful-shutdown.html

More Spring Boot recipes