The CancellationToken That Never Propagated: A Subtle ASP.NET Core Timeout Bug I Missed in Code Review
The CancellationToken That Never Propagated: A Subtle ASP.NET Core Timeout Bug I Missed in Code Review In the early stages of my career, I believed that if an HTTP request had a timeout set, the system was safe. I would configure HttpClient.Timeout or use RequestAborted , and I felt protected. I was wrong. Recently, I reviewed a codebase for a .NET Core application that was experiencing…
A subtle bug in ASP.NET Core handling could lead to application instability under heavy load. The issue stemmed from missing cancellation propagation to background tasks. When an HTTP request was made, the API quickly returned a 202 Accepted response, but the heavy operation ran asynchronously. This worked fine until users closed tabs or connections timed out.
Under high traffic, thousands of tasks started simultaneously, each waiting for a slow external API. The thread pool, finite in size, became saturated as each task awaited the HTTP response. Although async/await released threads back to the pool, CPU-bound work after the HTTP call wasn't canceled when the token was cancelled. This caused thread pool exhaustion, preventing new tasks from starting.
The fix involved propagating the CancellationToken from the top-level request into background tasks, checking the token at key points to stop processing if cancelled. This prevented resource leaks, stale data, and shutdown hangs. Developers commonly overlook the need to cancel background work tied to a request, often assuming timeouts alone suffice.
Always consider cancellation strategies when performing fire-and-forget operations, using appropriate cancellation tokens like RequestAborted for request-tied tasks or HostedService for application lifecycle-related work.
Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.