ASP.NET Core Kestrel and .NET ThreadPool: Boundary Between Burst and Starvation Under Concurrent Load
0 reputation · 19 Mar 2023, 00:27 UTC
0 reputation · 19 Mar 2023, 00:27 UTC
When an ASP.NET Core application hosted on Kestrel receives a sudden burst of concurrent requests, the .NET ThreadPool's hill-climbing algorithm may not inject worker threads quickly enough, causing requests to queue and latency to spike. The core uncertainty is where the boundary lies between a transient burst that the pool should absorb and sustained starvation that warrants architectural changes.
The ThreadPool's internal heuristic for distinguishing these states is not fully exposed for manual tuning, leaving operators to rely on indirect signals such as ThreadPool Queue Length and thread injection rate. Sync-over-async patterns can exacerbate the issue by blocking threads, but even purely asynchronous workloads may experience queueing during the one-thread-per-millisecond injection window. This analysis assumes .NET 8 or later on ASP.NET Core; behavior in earlier versions may differ and should be re-verified.
The specific heuristic remains opaque to configuration and monitoring surfaces. Which observable counters or configuration surfaces best expose the ThreadPool's burst-versus-starvation decision without risking regression? What alignment between Kestrel's concurrent connection limits and ThreadPool.MinThreads prevents queue buildup while preserving throughput? Is there a documented interoperability contract between Kestrel request dispatch and ThreadPool starvation detection that operators can use to set safe concurrency ceilings?
A thoughtful contribution can make all the difference. Be the first to share one.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.