Mastering Graceful Shutdown in Spring Boot 2.3: Best Practices & Code

This article explains why graceful shutdown is essential for Spring Boot and Spring Cloud applications, outlines key precautions, shows how Spring Boot 2.3 adds built‑in support, and provides configuration steps, code examples, and container‑specific behaviors to ensure clean service termination.

Programmer DD
Programmer DD
Programmer DD
Mastering Graceful Shutdown in Spring Boot 2.3: Best Practices & Code

Graceful shutdown for Spring Boot and Spring Cloud applications is a frequently asked question and a crucial production skill; this article summarizes the main points to consider.

Never use kill -9 for shutdown.

Use a thread pool for asynchronous threads so each can finish with Spring's lifecycle.

When a service registry is present, leverage Spring's shutdown event, Java's ShutdownHook, and service‑governance endpoints to ensure dependent services detect the instance stop within a discovery period.

Spring Boot 2.3 introduces built‑in configuration for graceful shutdown.

@RestController
public class DemoController {
    @GetMapping("/demo")
    public String demo() throws InterruptedException {
        // Simulate business processing time
        Thread.sleep(20 * 1000L);
        return "hello";
    }
}

If the server is killed while this endpoint processes a request, Spring Boot would normally close the container immediately, causing the business logic to fail and potentially leading to data inconsistency.

Graceful shutdown

Spring Boot 2.3 supports graceful shutdown for embedded web servers (Jetty, Reactor Netty, Tomcat, Undertow) and both reactive and servlet‑based applications.

Enable it with server.shutdown=graceful. The server stops accepting new requests and waits for active requests to finish within a configurable timeout.

Configuration experience

The supported shutdown behavior is defined by the following enum:

public enum Shutdown {
    GRACEFUL,
    IMMEDIATE;
}

timeout-per-shutdown-phase

The default timeout is 30 seconds; after this period the application shuts down regardless of ongoing tasks, so set it wisely.

Effect demonstration

Steps: request the service, trigger shutdown, the server receives the shutdown command, and the active request completes.

2020-05-17 18:28:28.940 INFO 60341 --- [extShutdownHook] o.s.b.w.e.tomcat.GracefulShutdown : Commencing graceful shutdown. Waiting for active requests to complete
2020-05-17 18:28:45.923 INFO 60341 --- [tomcat-shutdown] o.s.b.w.e.tomcat.GracefulShutdown : Graceful shutdown complete

Related knowledge

Use kill -2 (SIGINT) instead of kill -9 ; kill -2 triggers Java's ShutdownHook for graceful termination.

// ApplicationContext
@Override
public void registerShutdownHook() {
    if (this.shutdownHook == null) {
        this.shutdownHook = new Thread(SHUTDOWN_HOOK_THREAD_NAME) {
            @Override
            public void run() {
                synchronized (startupShutdownMonitor) {
                    doClose();
                }
            }
        };
        Runtime.getRuntime().addShutdownHook(this.shutdownHook);
    }
}
kill -9

forcefully kills the process without executing the ShutdownHook.

Graceful shutdown can also be invoked via the Actuator endpoint with a POST request to /actuator/shutdown .

@Endpoint(id = "shutdown", enableByDefault = false)
public class ShutdownEndpoint implements ApplicationContextAware {
    @WriteOperation
    public Map<String, String> shutdown() {
        Thread thread = new Thread(this::performShutdown);
        thread.setContextClassLoader(getClass().getClassLoader());
        thread.start();
    }

    private void performShutdown() {
        try {
            Thread.sleep(500L);
        } catch (InterruptedException ex) {
            Thread.currentThread().interrupt();
        }
        this.context.close();
    }
}

Different web containers handle graceful shutdown differently:

Web container

Behavior

Tomcat 9.0.33+

Stops receiving requests; new client requests wait until timeout.

Reactor Netty

Stops receiving requests; new client requests wait until timeout.

Undertow

Stops receiving requests; new client requests receive 503 immediately.

Graceful shutdown diagram
Graceful shutdown diagram
Configuration experience
Configuration experience
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.

JavaMicroservicesSpring BootGraceful ShutdownActuator
Programmer DD
Written by

Programmer DD

A tinkering programmer and author of "Spring Cloud Microservices in Action"

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.