.NET › Background Services

How does graceful shutdown work for a BackgroundService, and what role does CancellationToken play?

Intermediate

Answer

When the host begins shutting down (e.g., SIGTERM in a container, or Ctrl+C locally), it signals the CancellationToken passed to ExecuteAsync, and gives the service a configurable grace period (default 30 seconds via ShutdownTimeout) to finish current work and exit its loop cleanly before the host forcibly terminates it -- well-behaved background services should check the token frequently and respect cancellation in any long-running operations like Task.Delay or HTTP calls.
protected override async Task ExecuteAsync(CancellationToken stoppingToken) {
    while (!stoppingToken.IsCancellationRequested) {
        try {
            await DoWorkAsync(stoppingToken);
            await Task.Delay(TimeSpan.FromSeconds(10), stoppingToken);
        } catch (OperationCanceledException) {
            break;  // expected during shutdown
        }
    }
}
Real-world example A containerized worker service correctly handles Kubernetes' SIGTERM-then-SIGKILL shutdown sequence by respecting the CancellationToken, finishing its current message batch within the grace period instead of being abruptly killed mid-processing.

Common follow-ups: How do you configure the shutdown grace period (ShutdownTimeout)?;What happens if ExecuteAsync doesn't respect cancellation at all?