All Products
Search
Document Center

SchedulerX:Graceful shutdown for scheduled jobs

Last Updated:Feb 28, 2026

When an application restarts during a release, running scheduled jobs are interrupted, which can cause incomplete data processing or inconsistent states. SchedulerX graceful shutdown lets running jobs complete before the application process exits.

How it works

When graceful shutdown is enabled, the application process intercepts shutdown signals and delays its exit until in-flight jobs finish, up to an optional timeout.

  1. A shutdown signal is received (for example, kill -15, a Spring Boot shutdown event, or an HTTP request).

  2. Running jobs and tasks continue executing based on the configured shutdown mode.

  3. After all qualifying jobs complete or the timeout expires, the application process exits.

Graceful shutdown diagram

image

Prerequisites

Before you begin, make sure that you have:

  • SchedulerX client version 1.10.8 or later

Shutdown modes

SchedulerX supports two graceful shutdown modes for jobs running in standalone mode and distributed mode:

Mode Behavior When to use
WAIT_ALL (recommended) The application exits only after all jobs and tasks complete, including those in queue. Every scheduled job must finish to maintain data consistency.
WAIT_RUNNING The application exits after currently running jobs and tasks (with allocated threads) complete. Jobs and tasks in queue are dropped. Queued jobs can be safely retried or skipped.

Configure graceful shutdown

Add the following properties to your Spring Boot configuration:

# Shutdown mode: WAIT_ALL or WAIT_RUNNING
# Not configured by default (graceful shutdown is disabled).
spring.schedulerx2.graceShutdownMode=WAIT_ALL

# Maximum time (in seconds) to wait before forcing shutdown.
# Not configured by default (no timeout).
spring.schedulerx2.graceShutdownTimeout=10

# Enable the built-in HTTP shutdown endpoint. Default: false.
spring.schedulerx2.httpServerEnable=true

# Port for the HTTP shutdown endpoint. Default: 51886.
spring.schedulerx2.httpServerPort=51886
Parameter Description Default
spring.schedulerx2.graceShutdownMode Shutdown mode: WAIT_ALL or WAIT_RUNNING Not configured (disabled)
spring.schedulerx2.graceShutdownTimeout Maximum wait time in seconds before the process is forcefully terminated Not configured (no timeout)
spring.schedulerx2.httpServerEnable Enable the HTTP shutdown endpoint false
spring.schedulerx2.httpServerPort Port for the HTTP shutdown endpoint 51886
Important

Set graceShutdownTimeout to a value appropriate for your longest-running job. Without a timeout, a stuck job can block the application from ever shutting down.

Trigger graceful shutdown

Choose one of the following methods to trigger graceful shutdown. Method 1 (kill -15) works for any Java application. Methods 2 and 3 provide HTTP-based alternatives.

Method 1: Send SIGTERM with kill -15

SchedulerX registers a JVM shutdown hook that intercepts SIGTERM. Send the signal to the application process:

kill -15 <PID>

The process completes running jobs according to the configured shutdown mode, then exits.

Important

Do not run kill -9 directly. SIGKILL bypasses the JVM shutdown hook and terminates the process immediately, skipping graceful shutdown. If the process does not exit within an acceptable time after kill -15, then use kill -9 as a fallback.

Method 2: Use the Spring Boot actuator shutdown endpoint

For Spring Boot applications, use the built-in actuator to trigger a shutdown event. SchedulerX responds to Spring container shutdown events and completes running jobs before the application exits.

  1. Add the actuator dependency to your pom.xml:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
  1. Enable the shutdown endpoint in your application properties:

management.endpoint.shutdown.enabled=true
management.endpoints.web.exposure.include=shutdown
  1. Trigger the shutdown:

curl -X GET http://<node-ip>:<port>/actuator/shutdown

Method 3: Use the SchedulerX HTTP endpoint

Enable the built-in SchedulerX HTTP endpoint:

spring.schedulerx2.httpServerEnable=true
spring.schedulerx2.httpServerPort=51886

Trigger the shutdown:

curl -X GET http://<node-ip>:51886/schedulerx/worker/shutdown

Integrate into deployment workflows

Self-managed continuous delivery (CD) pipeline

Include the graceful shutdown logic in the stop script of your CD pipeline. The following example sends SIGTERM, polls for process exit, and falls back to SIGKILL after a timeout:

image
# After starting the application, write the PID to app.pid.
PID="{Application deployment path}/app.pid"
FORCE=1
if [ -f ${PID} ]; then
  TARGET_PID=`cat ${PID}`
  kill -15 ${TARGET_PID}
  loop=1
  while(( $loop<=5 ))
  do
    # health: Check whether the application process is still running.
    # Replace with your own health check command.
    health
    if [ $? == 0 ]; then
      echo "check $loop times, current app has not stop yet."
      sleep 5s
      let "loop++"
    else
      FORCE=0
      break
    fi
  done
  if [ $FORCE -eq 1 ]; then
  	echo "App(pid:${TARGET_PID}) stop timeout, forced termination."
    kill -9 ${TARGET_PID}
  fi
  rm -rf ${PID}
  echo "App(pid:${TARGET_PID}) stopped successful."
fi

Kubernetes PreStop hook

Use the Kubernetes Pod preStop lifecycle hook to trigger graceful shutdown before a Pod is terminated.

Option A: Exec script

Run a script or send SIGTERM directly:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: my-app-container
        image: my-app-image:latest
        lifecycle:
          preStop:
            exec:
              # command: ["/bin/sh", "-c", "kill -15 PID && sleep 30"]
              command: ["/bin/sh", "-c", "Script path /stop.sh"] 

Option B: HTTP request

Call the appropriate HTTP endpoint based on your application type:

  • Spring Boot applications: Set path to /actuator/shutdown.

  • Non-Spring applications: Set path to /schedulerx/worker/shutdown after enabling the SchedulerX HTTP endpoint.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: my-app-container
        image: my-app-image:latest
        lifecycle:
          preStop:
            httpGet:
              path: /schedulerx/worker/shutdown
              port: 51886
              scheme: HTTP

Alibaba Cloud platform integration

If you deploy through Enterprise Distributed Application Service (EDAS) or through Microservices Engine (MSE) with Container Service for Kubernetes (ACK), SchedulerX graceful shutdown integrates automatically after you enable graceful shutdown on the platform. For details, see:

Best practices

  • Set a shutdown timeout. Without a timeout, a long-running or stuck job blocks the shutdown indefinitely. Set graceShutdownTimeout to a value slightly longer than the expected maximum job duration.

  • Avoid kill -9 as the first action. Always send SIGTERM (kill -15) first and wait for graceful shutdown to complete. Use SIGKILL (kill -9) only as a last resort after the timeout expires.

  • Use WAIT_ALL for data-sensitive workloads. WAIT_RUNNING drops queued jobs, which may cause missed executions. Choose WAIT_ALL unless queued jobs are safely retriable.

  • Verify no active jobs before shutdown. In production, check job execution status before triggering a shutdown to avoid unnecessary wait times or retries.

  • Test graceful shutdown in staging first. Validate that your shutdown configuration, timeout, and integration method work correctly before applying them to production.