Backend Development 19 min read

Graceful Shutdown of Spring Boot Applications and the Risks of Using kill -9

This article explains how the Linux kill -9 command can cause data loss and service instability, demonstrates safer alternatives such as kill -15 and Spring Boot's built‑in shutdown mechanisms, and provides code examples for implementing graceful termination, custom shutdown hooks, and pre‑destroy data backup in Java backend services.

Top Architect
Top Architect
Top Architect
Graceful Shutdown of Spring Boot Applications and the Risks of Using kill -9

The kill command sends signals to processes; by default it uses SIGTERM (15) to request termination, while SIGKILL (9) forces an immediate stop, similar to a power outage.

Using kill -9 on a running service can leave transactions incomplete, especially with non‑transactional storage engines like MyISAM, leading to data inconsistency (e.g., money deducted from one account but not credited to another).

In distributed systems, abruptly killing a service can break distributed transactions, causing unrecoverable errors.

Graceful termination alternatives

kill -15 pid sends SIGTERM , allowing the application to finish ongoing work before exiting. A simple Spring Boot controller example shows a request that sleeps for 100 seconds; when kill -15 is issued, the thread receives an InterruptedException , logs the interruption, and the application shuts down cleanly.

@GetMapping("/test")
public String test() {
    log.info("test --- start");
    try { Thread.sleep(100000); } catch (InterruptedException e) { e.printStackTrace(); }
    log.info("test --- end");
    return "test";
}

Spring Boot also provides a built‑in shutdown script ( shutdown.sh ) and the Actuator /shutdown endpoint, which can be enabled in application.yml :

management:
  endpoints:
    web:
      exposure:
        include: shutdown
  endpoint:
    shutdown:
      enabled: true

Adding Actuator to the project:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

For more control, a custom Tomcat connector can be used to pause new requests and wait for existing threads to finish. The ElegantShutdownConfig class implements TomcatConnectorCustomizer and listens for ContextClosedEvent to pause the connector and await termination of the thread pool for a configurable waitTime (default 10 seconds).

public class ElegantShutdownConfig implements TomcatConnectorCustomizer, ApplicationListener
{
    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");
            }
        }
    }
}

The custom config is registered as a bean and added to the embedded Tomcat factory:

@Bean
public ElegantShutdownConfig elegantShutdownConfig() { return new ElegantShutdownConfig(); }

@Bean
public ServletWebServerFactory servletContainer() {
    TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
    tomcat.addConnectorCustomizers(elegantShutdownConfig());
    return tomcat;
}

To perform actions just before the JVM stops, use the @PreDestroy annotation. The example DataBackupConfig prints a backup message when the application context is closed.

@Configuration
public class DataBackupConfig {
    @PreDestroy
    public void backData() {
        System.out.println("Backing up data...");
    }
}

Overall, the article demonstrates why kill -9 should be avoided for production services, how to use kill -15 or Spring Boot’s graceful shutdown features, and provides ready‑to‑use code snippets for safe termination and cleanup.

BackendJavalinuxSpring BootGraceful ShutdownKill Command
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

login 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.