DbContext Pooling in ASP.NET Core: Boost Performance Safely

September 2, 2025 · 6 min

I once spent the better part of a week chasing a bug that only appeared in our staging environment under heavy load. A user from one organization would suddenly see data belonging to another. We’d check the logs, query the database directly, and everything looked fine. It was a ghost.

The culprit? A single line change someone made to “optimize” our database access: switching AddDbContext to AddDbContextPool. That optimization introduced a state-sharing bug that was nearly impossible to reproduce locally.

DbContext pooling in EF Core is one of those features that promises a big performance win, but it comes with a massive, sneaky gotcha. Let’s break down what it is, where it shines, and how to use it without shooting yourself in the foot.

So, what’s DbContext pooling anyway?

Normally, when you register your DbContext in an ASP.NET Core app, you use a scoped lifetime. This is the default and the safest option.

// The standard, safe way: A new instance for every HTTP request.
services.AddDbContext<AppDbContext>(options => 
    options.UseSqlServer(connectionString));

This means for every single web request, the dependency injection container creates a brand-new DbContext instance. When the request is over, that instance is thrown away. Simple, clean, and isolated.

DbContext pooling changes the game. Instead of creating a new instance every time, it keeps a “pool” of DbContext instances ready to go.

// The high-performance way: …

Read more