Why kill -9 Can Crash Your Spring Boot Service and How to Shut It Down Gracefully

This article explains the dangers of using the kill -9 command on Java services, illustrates how it can cause data loss, and presents several graceful shutdown techniques for Spring Boot—including SIGTERM, Actuator endpoints, custom Tomcat shutdown hooks, and @PreDestroy backups—complete with code examples and screenshots.

Java Backend Technology
Java Backend Technology
Java Backend Technology
Why kill -9 Can Crash Your Spring Boot Service and How to Shut It Down Gracefully

kill -9 pid ???

kill sends a signal to a process; the default signal is SIGTERM (15) which asks the process to terminate, while SIGKILL (9) forces an immediate termination.

Using kill -9 on a running Java service is risky because it abruptly stops the JVM, potentially leaving databases in an inconsistent state (e.g., MyISAM tables) or breaking distributed transactions.

Graceful shutdown

kill -15 pid

Sending SIGTERM ( kill -15) allows the application to handle the interruption, finish ongoing work, and shut 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";
}

When the thread is sleeping, kill -15 triggers an InterruptedException, which is caught, allowing the method to log "test --- end" before the process exits.

Actuator shutdown

Spring Boot’s Actuator provides a built‑in shutdown endpoint.

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

# application.yml
management:
  endpoints:
    web:
      exposure:
        include: shutdown
  endpoint:
    shutdown:
      enabled: true
server:
  port: 8888

Calling /actuator/shutdown returns a friendly message and stops the service after completing current requests.

Custom elegant shutdown

For finer control, implement a Tomcat connector customizer that pauses new requests and waits for the thread pool to finish.

class ElegantShutdownConfig implements TomcatConnectorCustomizer, ApplicationListener<ContextClosedEvent> {
    private volatile Connector connector;
    private final int waitTime = 10; // seconds

    @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();
            try {
                if (!pool.awaitTermination(waitTime, TimeUnit.SECONDS)) {
                    System.out.println("Forceful shutdown may be required");
                }
            } catch (InterruptedException ex) {
                Thread.currentThread().interrupt();
            }
        }
    }
}

Register the config as a bean and attach it 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;
}

Data backup on shutdown

Spring’s lifecycle annotation @PreDestroy can run custom logic (e.g., data backup) just before the container stops.

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

When the application receives a shutdown signal, the @PreDestroy method executes, allowing you to persist state or perform cleanup.

Spring Boot shutdown log showing start, interrupt, and end
Spring Boot shutdown log showing start, interrupt, and end
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.

BackendJavaSpring BootGraceful ShutdownKill Commandprocess termination
Java Backend Technology
Written by

Java Backend Technology

Focus on Java-related technologies: SSM, Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading. Occasionally cover DevOps tools like Jenkins, Nexus, Docker, and ELK. Also share technical insights from time to time, committed to Java full-stack development!

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.