How to Gracefully Shut Down a SpringBoot Application Without Data Loss
This article explains what graceful shutdown means for a SpringBoot service, why force‑killing the process is risky, and presents multiple safe shutdown techniques—including Actuator endpoints, ApplicationContext.close(), PID‑based killing, and SpringApplication.exit()—along with listener examples for resource cleanup.
1. Introduction
Graceful shutdown means sending a stop command to an application while ensuring that in‑flight business operations complete before the service stops.
Stop accepting new requests.
Allow ongoing requests, scheduled tasks, MQ consumers, etc., to finish and prevent new tasks from starting.
When ready to close, optionally signal downstream services to take over.
Force‑killing the process (e.g.,
kill -9 <pid>) can cause data loss, resource leaks, or deadlocks such as unreleased Redis locks.
How can we shut down a SpringBoot application safely without affecting business?
2. Solution Practice
2.1 Method 1 – Use Actuator’s shutdown endpoint
Add
spring-boot-starter-actuatorand enable the shutdown endpoint in
application.properties:
<code>management.endpoint.shutdown.enabled=true
management.endpoints.web.exposure.include=shutdown</code>Then send a POST request to
http://127.0.0.1:8080/actuator/shutdownto stop the service.
2.2 Method 2 – Call ApplicationContext.close()
Obtain the
ApplicationContextand invoke its
close()method. Example:
<code>@SpringBootApplication
public class Application {
public static void main(String[] args) throws Exception {
ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
TimeUnit.SECONDS.sleep(10);
context.close();
}
}</code>You can also expose a controller that calls
((ConfigurableApplicationContext)context).close().
2.3 Method 3 – Kill the process by PID
Write the PID to a file using
ApplicationPidFileWriterand later execute
kill $(cat /path/app.pid). This is a common Linux approach.
2.4 Method 4 – Use SpringApplication.exit()
Call
SpringApplication.exit(context, () -> 0)to obtain an exit code and then
System.exit(exitCode). Example:
<code>@SpringBootApplication
public class Application {
public static void main(String[] args) throws Exception {
ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
TimeUnit.SECONDS.sleep(5);
exitApplication(context);
}
public static void exitApplication(ConfigurableApplicationContext ctx) {
int exitCode = SpringApplication.exit(ctx, () -> 0);
System.exit(exitCode);
}
}</code>3. Other Listeners
3.1 ApplicationListener
Implement
ApplicationListenerto react to
ContextClosedEventand clean up resources such as database connection pools before the bean container is destroyed.
<code>@Component
public class JobTaskListener implements ApplicationListener<ApplicationEvent> {
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ContextClosedEvent) {
System.out.println("Shutting down scheduled tasks");
}
}
}</code>3.2 @PreDestroy
Annotating a method with
@PreDestroy(or implementing
DisposableBean) provides the same shutdown hook.
<code>@Component
public class AppDestroyConfig {
@PreDestroy
public void preDestroy() {
System.out.println("Application is shutting down...");
}
}</code>4. Summary
The article presents several ways to safely stop a SpringBoot service, including Actuator’s shutdown endpoint, direct context closing, PID‑based killing, and SpringApplication’s exit method, as well as auxiliary listeners for resource cleanup.
macrozheng
Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.
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.