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.

Top Architect
Top Architect
Top Architect
Graceful Shutdown of Spring Boot Applications: Avoiding the Pitfalls of kill -9

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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaProcess Managementspring-bootGraceful ShutdownLinux kill
Top Architect
Written by

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.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.