Graceful shutdown and lifecycle ordering
Stop taking new work, finish what is in flight, then release resources - in that order.
Open this lesson in the learning hubKey points
- A container sends SIGTERM and starts a countdown. Without graceful shutdown, the JVM exits immediately and every in-flight request becomes a client-side error.
server.shutdown=gracefulmakes the connector stop accepting new connections while existing requests finish, bounded byspring.lifecycle.timeout-per-shutdown-phase.- There is a subtlety that graceful shutdown alone does not solve: the load balancer may still be routing to this pod when SIGTERM arrives. Failing readiness first, then pausing, is what drains traffic cleanly.
- Shutdown runs
SmartLifecyclebeans in reverse phase order, so something started early is stopped last. That is how a message consumer stops before the datasource it writes through closes. @PreDestroyruns during context close, after lifecycle stop. It is the right place to flush a buffer, and the wrong place to make a slow network call.- Kubernetes kills the pod when its termination grace period expires, so the shutdown timeout must be shorter than that value or the process is killed mid-request anyway.
Example
server:
shutdown: graceful # stop accepting, let in-flight requests finish
spring:
lifecycle:
timeout-per-shutdown-phase: 25s # must be < the pod terminationGracePeriodSeconds
management:
endpoint:
health:
probes:
enabled: true # /actuator/health/liveness and /readiness
---
# The consumer stops before anything it depends on. Reverse phase order on stop
# is what guarantees that, so no phase juggling is needed at the call site.
#
# start: phase -100 (warmup) -> phase 0 (consumer) -> MAX (web server)
# stop: MAX (web server) -> phase 0 (consumer) -> phase -100
#
# Kubernetes side - drain BEFORE the process is asked to stop:
#
# lifecycle:
# preStop:
# exec:
# command: ["sh", "-c", "sleep 5"] # let endpoints propagate first
# terminationGracePeriodSeconds: 40 # > the 25s above
Fail readiness, wait for the load balancer to notice, then let in-flight work finish inside a timeout shorter than the platform grace period.
This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Spring Boot course, and every lesson in it is listed on the Spring Boot contents page.