In high-scale ASP.NET Core applications, instantiating a new DbContext for every single HTTP request can become a major performance bottleneck. While DbContext is designed to be lightweight, the repeated initialization of its internal services and state machines consumes significant CPU cycles. DbContext Pooling solves this by recycling existing context instances.
By default, AddDbContext registers your context as Scoped. This means for every incoming request, a new instance is created and then disposed of at the end. This is safe, but computationally expensive under heavy load.
// Standard (Scoped) registration
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
With pooling enabled, EF Core maintains a pool of initialized instances. When a request starts, it "rents" a context from the pool. When the request ends, EF Core "resets" the context (clearing its change tracker) and returns it to the pool instead of destroying it.
// Optimized (Pooled) registration
builder.Services.AddDbContextPool<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString),
poolSize: 1024); // Specify the maximum number of instances to maintain
You CANNOT use DbContext Pooling if your DbContext constructor accepts other Scoped services via Dependency Injection (like a UserContext that identifies the current logged-in user). Because pooled contexts are long-lived and reused across different requests, injecting a request-specific scoped service into the constructor would result in "Captive Dependencies," leaking data between unrelated users!
If your application handles thousands of requests per second and your DbContext doesn't require custom state in its constructor, pooling can reduce CPU overhead by up to 20-30% in high-throughput microservices. For standard business applications, the default Scoped registration is usually sufficient.
Q: "Does DbContext Pooling also pool the underlying physical SQL Server database connections?"
Architect Answer: "No. It is crucial to distinguish between the two. `DbContext Pooling` manages the lifecycle of the C# EF Core objects in RAM to save CPU initialization cycles. `Database Connection Pooling` is a separate mechanism managed by the ADO.NET provider (like SqlClient) that keeps actual TCP sockets open to the database to save network handshake time. You can have Connection Pooling habilitated without DbContext Pooling, but you almost always want both enabled for production systems."