Daniel Stock’s Post

A subtle mistake I’ve seen in many APIs isn’t about architecture… it’s about how we handle async code. Everything looks correct on the surface:   • Async endpoints   • Await everywhere   • Clean structure But then performance starts degrading under load. Now picture this:   • You have an API built with ASP.NET Core.   • Your service calls the database using async methods from Entity Framework Core. So far, so good. But somewhere in the code, a small decision slips in: .𝗥𝗲𝘀𝘂𝗹𝘁 or .𝗪𝗮𝗶𝘁() It works locally. It even passes tests. But under real load, this becomes a problem. 𝗪𝗵𝘆? Because you’re blocking threads in a system designed to be non-blocking. Each blocked thread:   • Holds resources longer than necessary   • Reduces throughput   • Increases latency for other requests In extreme cases, this leads to thread pool starvation. Now your “scalable” API starts behaving like a bottleneck. The fix is simple, but requires discipline:   • Go fully async end-to-end   • Never mix sync-over-async   • Return Task all the way up the call stack   • Use await consistently And this connects directly with your database layer: Whether you’re using SQL Server or PostgreSQL, async queries help free threads while waiting for I/O. But only if you don’t block them afterward. What makes this tricky is that the issue doesn’t show up immediately. It only appears when:   • Traffic increases   • Latency matters   • Concurrency grows This is one of those small details that separates code that works from systems that scale. #DotNet #ASPNetCore #EntityFramework #AsyncProgramming #Performance #BackendDevelopment #Microservices #Cloud #SQLServer #PostgreSQL #SoftwareEngineering #Scalability

I remember troubleshooting a legacy migration to .NET Core where the system would randomly hang under peak traffic, even though CPU usage was low. We found a few .Result calls hidden inside a custom logging middleware. It was a textbook case of Thread Pool Starvation: the threads were all waiting for each other to finish, creating a deadlock that didn't exist in dev but crushed production.

Like
Reply

To view or add a comment, sign in

Explore content categories