All articles
    Enterprise

    Why Your .NET Application Is Slow: 8 Common Performance Issues

    June 25, 2026 9 min read
    .NETC#PerformanceEntity FrameworkASP.NET Core

    Most .NET Performance Problems Are Predictable

    After shipping and maintaining .NET applications across enterprise, healthcare, and government contexts, the same performance issues appear repeatedly. They are not exotic or difficult to diagnose once you know what to look for. Here are the eight most common causes of slow .NET applications and how to address each one.

    1. Blocking Async Code with .Result or .Wait()

    Calling .Result or .Wait() on a Task in an ASP.NET Core application blocks a thread synchronously while waiting for the async operation to complete. Under load, this exhausts the thread pool and causes request queuing that looks like a server that cannot handle traffic.

    The fix is consistent async/await all the way up the call stack. If a method calls an async database operation, it must be async itself. Mixing synchronous and asynchronous code creates deadlocks in certain execution contexts, particularly when SynchronizationContext is present.

    2. N+1 Queries in Entity Framework

    The most common Entity Framework performance problem: you load a list of entities, then access a navigation property on each one in a loop, causing a separate database query for each item in the list. 100 items becomes 101 queries. This is invisible in development with small datasets and catastrophic in production with large ones.

    Fix with .Include() to eager load related entities in a single query, or split queries for large collections to avoid cartesian product blowup. For read-heavy paths with complex joins, drop to raw SQL or Dapper where EF's query generation is suboptimal.

    3. Synchronous HTTP Calls in Request Handlers

    Any synchronous network call inside a request handler ties up a thread for the entire duration of that call. A third-party API that takes 800ms to respond, called synchronously, means your ASP.NET Core thread is blocked for 800ms and cannot handle other requests.

    All HTTP client calls must use HttpClient with await. Use IHttpClientFactory for lifecycle management and connection pooling. Never use the synchronous overloads of HttpClient in request handling code.

    4. Missing Database Indexes

    A query that filters on an unindexed column performs a full table scan. On a table with 10 rows this is unnoticeable. On a table with 10 million rows, it is the reason your API response time is 4 seconds instead of 40ms.

    Use Entity Framework's built-in logging or SQL Server's Query Store to identify slow queries. Look for sequential scans in execution plans. Add indexes on columns that appear in WHERE clauses, JOIN conditions, and ORDER BY clauses in your most frequent queries. Composite indexes matter: the order of columns in an index determines which queries it covers.

    5. Connection Pool Exhaustion

    Each database connection is a limited resource. The default SQL Server connection pool has 100 connections. If your application opens connections without closing them, uses using blocks incorrectly, or has a spike that opens more connections than the pool allows, new requests queue waiting for a connection and eventually time out.

    The diagnostic: watch for TimeoutException from the connection pool, or use performance counters to track pool usage. The fix is ensuring every DbConnection is closed in a using block or with explicit disposal, and considering whether connection pool size needs to be increased for your concurrency level.

    6. Large Object Allocations and GC Pressure

    The .NET garbage collector has a Large Object Heap (LOH) for allocations over 85,000 bytes. LOH collection is expensive and only happens during full GC. Applications that repeatedly allocate large byte arrays (for file processing, image handling, or large response serialization) without pooling cause frequent full GC pauses that manifest as latency spikes under load.

    Use ArrayPool<T> for reusable byte arrays. For streaming large responses, use IAsyncEnumerable or streaming serialization rather than loading entire results into memory. Profile with dotMemory or the Visual Studio Diagnostic Tools to identify allocation hotspots.

    7. Missing Response Caching

    Requests for data that does not change frequently hitting the database on every call is expensive at scale. A product catalog endpoint called 1,000 times per minute that rebuilds the same JSON from the database each time is a solvable problem.

    ASP.NET Core's built-in response caching middleware caches responses for GET requests with appropriate cache headers. For more control, IMemoryCache for in-process caching and IDistributedCache (backed by Redis) for multi-instance deployments give you programmatic cache management with TTL and invalidation.

    8. Synchronous File I/O

    Reading or writing files using the synchronous overloads of File.Read, File.Write, or StreamReader in an ASP.NET Core request handler blocks a thread during the I/O wait. Under concurrent load, this reduces throughput exactly like synchronous database or HTTP calls.

    Use the async overloads: File.ReadAllTextAsync, File.WriteAllTextAsync, and the async methods on StreamReader and StreamWriter. For high-volume file operations, consider Azure Blob Storage with the async SDK, which handles connection pooling and retry logic that file system operations do not provide.

    FriendsBit has diagnosed and resolved .NET performance issues across enterprise platforms, including the WCF-to-REST migration for the United Nations that improved indexing throughput 3x by eliminating synchronous blocking patterns. If your .NET application has performance problems that are costing you in infrastructure or user experience, get in touch and we can run a diagnostic review.

    K

    Khalil

    Senior Software Engineer & Founder, FriendsBit

    8+ years building enterprise software, API integrations, and cloud systems across healthcare, government, and SaaS. React, Next.js, Go, .NET, React Native, and AWS.

    LinkedIn

    Have a similar challenge?

    We've solved problems like this before. Tell us about your project and we'll get back to you within 24 hours.

    Get in touch

    Related service

    Enterprise Software

    View service