Choosing the Right DbContext Lifetime

AddDbContext, AddDbContextPool, AddDbContextFactory, AddPooledDbContextFactory — a simple way to decide which one to use in EF Core.

It's easier than it sounds to end up using the wrong DbContext lifetime without even noticing.

EF Core gives you four ways to register it:

  • AddDbContext()
  • AddDbContextPool()
  • AddDbContextFactory()
  • AddPooledDbContextFactory()

And the question is always the same: which one am I actually supposed to use?

Before picking one, there's a single question worth asking: where will this code run? The answer usually tells you which registration method fits.


#AddDbContext()

Use it when your code runs inside a typical HTTP request.

One request gets one DbContext instance. That's exactly what most web applications need — simple, predictable, and safe.

CSHARP
builder.Services.AddDbContext<AppDbContext>(options =>
    options.UseSqlServer(connectionString));

#AddDbContextPool()

Use it when your API handles a high volume of requests.

Instead of creating a new instance per request, it reuses DbContext instances from a pool, which reduces allocation overhead.

CSHARP
builder.Services.AddDbContextPool<AppDbContext>(options =>
    options.UseSqlServer(connectionString));

Pooling can improve throughput in the right scenario. But like every optimization, measure before adopting it.


#AddDbContextFactory()

Use it when your code runs inside background services, scheduled jobs, Task.WhenAll, or any parallel operation.

A DbContext isn't thread-safe. Each concurrent operation needs its own instance, and the factory creates a fresh one on demand.

CSHARP
builder.Services.AddDbContextFactory<AppDbContext>(options =>
    options.UseSqlServer(connectionString));
CSHARP
public class ReportGenerator(IDbContextFactory<AppDbContext> factory)
{
    public async Task GenerateAsync()
    {
        await using var context = await factory.CreateDbContextAsync();
        // ...
    }
}

#AddPooledDbContextFactory()

Use it when you need independent DbContext instances while also benefiting from pooling — a good fit for high-throughput background processing.

CSHARP
builder.Services.AddPooledDbContextFactory<AppDbContext>(options =>
    options.UseSqlServer(connectionString));

It combines the flexibility of a factory with the performance of a pool.


#None of them is "better"

That's the part that's easy to miss: these four methods aren't ranked from worst to best. They're designed for different execution models, and EF Core gives you all four so the registration can match how your code actually runs.

Once the question becomes "where does this run?" instead of "which one is best?", the choice is usually obvious.

#ef-core #dotnet #dbcontext