Graceful Shutdown of Spring Boot Applications: Avoiding the Pitfalls of kill -9
This article explains how the Linux kill -9 command can cause data inconsistency and service disruption, demonstrates why it should be avoided in production, and provides several graceful shutdown techniques for Spring Boot—including using kill -15, the built‑in shutdown hook, Actuator endpoints, and a custom Tomcat connector configuration—along with code examples and best‑practice recommendations.
The Linux kill -9 pid command forcefully terminates a process, which is equivalent to an abrupt power loss; when used on services that handle transactions (e.g., MySQL InnoDB vs. MyISAM) it can lead to data loss or inconsistency, especially in distributed systems.
Because kill -9 does not allow the application to release resources or finish ongoing work, the article recommends using more graceful termination signals such as kill -15 pid, which sends SIGTERM and gives the JVM a chance to shut down cleanly.
For Spring Boot applications, three graceful shutdown approaches are presented:
Calling the Tomcat shutdown script ( shutdown.bat/shutdown.sh) to stop the container.
Enabling the Actuator shutdown endpoint in application.yml and invoking it via HTTP.
Implementing a custom ElegantShutdownConfig that pauses the Tomcat connector, waits for thread‑pool termination, and then closes the context.
Example controller used for testing:
@GetMapping(value = "/test")
public String test(){
log.info("test --- start");
try { Thread.sleep(100000); } catch (InterruptedException e) { e.printStackTrace(); }
log.info("test --- end");
return "test";
}Custom shutdown configuration class:
public class ElegantShutdownConfig implements TomcatConnectorCustomizer, ApplicationListener<ContextClosedEvent> {
private volatile Connector connector;
private final int waitTime = 10;
@Override public void customize(Connector connector) { this.connector = connector; }
@Override public void onApplicationEvent(ContextClosedEvent event) {
connector.pause();
Executor executor = connector.getProtocolHandler().getExecutor();
if (executor instanceof ThreadPoolExecutor) {
ThreadPoolExecutor pool = (ThreadPoolExecutor) executor;
pool.shutdown();
if (!pool.awaitTermination(waitTime, TimeUnit.SECONDS)) {
System.out.println("Please try forceful shutdown");
}
}
}
}Additionally, the article mentions using the @PreDestroy annotation to perform backup or cleanup tasks before the JVM exits.
Overall, the guide advises avoiding kill -9 in production, preferring graceful termination methods that allow Spring Boot services to finish in‑flight requests, release resources, and maintain data integrity.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Top Architect
Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
