Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Spring TaskScheduler shutdown: stop new polls and account for in-flight work

Last updated: 30 Sept 20264 min read
tutorial
IntermediateBy AITrove Editorial

Scheduler shutdown stops future polling callbacks; it does not automatically reverse an external operation already in flight.

Download Spring source kit

The checked lifecycle

The local test initializes one ThreadPoolTaskScheduler, schedules a fixed-delay poller, waits for one delivered event, cancels the returned ScheduledFuture and calls shutdown in a finally block. The cancelled future reports cancelled. This is enough to keep the test from leaving a polling thread behind.

The test does not start a graceful deployment drain, wait for a slow transport, renew an expiring lease, or restart after a kill. A callback could be inside a remote publish when the process receives a stop signal. The lease must expire or renew; the consumer marker must handle a retry.

Design the stop budget

For a service, stop accepting new claims, allow current callbacks a bounded completion window, and leave unacknowledged rows recoverable. A forced termination may happen at any point. Do not mark work delivered merely because a shutdown hook ran. Configure scheduler lifecycle with the application context and measure drain duration under realistic transport timeouts.

A callback that catches every exception without recording state can hide lost work. Keep the row transition, error category and event ID available for operators. Backlog age will show stalled recovery after a restart.

Checked source

Java
var future = scheduler.scheduleWithFixedDelay(poller, Duration.ofMillis(20));
try { assertTrue(delivered.await(3, TimeUnit.SECONDS)); }
finally { future.cancel(false); scheduler.shutdown(); }

Verification boundary

ScheduledOutboxPollerTest.scheduledWorkerConsumesCommittedRowAndStops. The excerpt is shortened or a labelled design sketch; the source kit contains the complete checked fixture.

Costs and limits

The test verifies cancellation and shutdown after one successful callback. It does not assert application-context lifecycle, in-flight timeout handling, process termination or deployment drain.

Common Mistakes

  • Do not assume cancel(false) interrupts a running callback.
  • Do not delete a leased row during shutdown.
  • Do not call one clean test teardown a restart-recovery test.

Read next

Spring TaskScheduler: poll committed outbox rows in the background, Spring outbox claims: lease expiry and token-fenced acknowledgement, Spring scheduled relay: recover when the consumer commits before acknowledgement, Spring relay integration tests: prove the boundaries H2 cannot.

Continue with lease race checks

Continue with Spring outbox lease renewal: extend only the current owner.

Release boundary continuation

Continue with Spring worker shutdown: release admission before a lease expires.

spring
spring-boot
scheduled-relay
Storage details