tags / Performance

Performance tips and tricks

How to Avoid Loading an Entire Table into Memory

Need only active customers?

Filter them in the database.

Instead of:

var customers = await context.Customers.ToListAsync();

var activeCustomers = customers
    .Where(x => x.IsActive)
    .ToList();

Prefer:

var activeCustomers = await context.Customers
    .Where(x => x.IsActive)
    .ToListAsync();

The difference is where filtering happens.

How to Avoid Loading an Entire Table into Memory

The first approach:

  • Loads every row
  • Transfers every row
  • Stores every row in memory
  • Filters afterward

The second approach lets the database return the rows you requested.

If you need 100 customers from a table containing 1,000,000 rows, filtering before ToListAsync() tends to matter.

How to Stop Work When a Request Is Cancelled

Client disconnected while your API is still doing expensive work?

Pass the CancellationToken.

public async Task<IActionResult> GetOrders(
    CancellationToken cancellationToken)
{
    var orders = await context.Orders
        .ToListAsync(cancellationToken);

    return Ok(orders);
}

Propagate the token through operations that support cancellation:

  • Database queries
  • HTTP calls
  • Background operations
  • Delays
  • Long-running async workflows

Cancellation doesn't make every operation disappear immediately.

It signals downstream operations that the caller no longer needs the result.

If the request is gone, continuing work is often unnecessary.

How to Speed Up Read-Only EF Core Queries

Reading data that you don't plan to update?

Consider AsNoTracking().

var products = await context.Products
    .AsNoTracking()
    .Where(x => x.IsActive)
    .ToListAsync();

By default, EF Core tracks entities so it can detect changes and persist them later.

For read-only scenarios, that tracking work might not be needed.

How to Speed Up Read-Only EF Core Queries

AsNoTracking() helps by:

  • Avoiding change tracking
  • Reducing tracking-related memory usage
  • Making the intent of the query explicit
  • Working well for API reads and reporting
  • Keeping read-only queries focused on reading

If you don't plan to change the entity, consider asking EF Core not to track changes.

How to Avoid an Infinite Loop

Does your loop never stop?

Give it a condition that eventually becomes false.

How to Avoid an Infinite Loop

Things to check:

  • Make sure the condition changes
  • Increment your counter
  • Update variables used by the condition
  • Use break when appropriate
  • Avoid accidental while (true) loops

A loop continues while its condition evaluates to true.

If the condition stays true forever, the loop also runs forever.

How to Check If a Collection Contains an Item

Need to know whether a collection contains a specific item?

Use Contains.

How to Check If a Collection Contains an Item

Common examples:

  • Check whether a list contains a value
  • Check whether a set contains an item
  • Use the result in an if statement
  • Continue when the item exists
  • Handle the case when it doesn't

Contains returns true when the collection contains the specified item and false when it doesn't.

How do you check whether something exists in a collection?

How to Build a SQL Query

Need to retrieve data from a database?

A typical SQL query consists of these clauses:

  • SELECT to choose columns
  • FROM to specify the table
  • JOIN to combine related tables
  • WHERE to filter rows
  • GROUP BY to group results
  • HAVING to filter groups
  • ORDER BY to sort data
  • OFFSET / FETCH or LIMIT to paginate

Not every query needs every clause, but this is the structure you'll see in most SQL statements.

How to Build a SQL Query

Understanding what each clause does makes reading and writing SQL much easier.

How to Increase Throughput

Consider parallel execution.

Common approaches:

  • Use Task.WhenAll()
  • Process independent tasks concurrently
  • Increase consumer instances
  • Batch operations when possible
  • Remove unnecessary bottlenecks

Parallel processing allows multiple operations to run at the same time rather than waiting for each to finish.

For example:

  • 10 API calls executed sequentially may take 10 seconds
  • 10 API calls executed in parallel may take around 1 second

Of course, parallelism isn't free. Databases, external APIs, and infrastructure still have limits.

But if your workload is independent, parallel execution is often one of the simplest ways to increase throughput.

What was the biggest throughput improvement you've achieved?

How to Increase Throughput

How to Speed Up SQL Queries

Queries running slowly?

Consider adding an index.

How to Speed Up SQL Queries

Indexes help SQL Server:

  • Find data faster
  • Reduce table scans
  • Improve filtering performance
  • Improve sorting performance
  • Improve join performance

Not every column needs an index, but columns used in WHERE clauses often benefit from one.

What is your favorite indexing strategy?

How to Use SaveChangesAsync in .NET

Want asynchronous database writes in EF Core?

Use SaveChangesAsync() instead of SaveChanges().

How to Use SaveChangesAsync in .NET

Benefits:

  • Doesn't block the calling thread
  • Works better under load
  • Integrates with async/await
  • Recommended for ASP.NET Core applications
  • Available since EF Core was released

What other EF Core performance tips do you use?