We have a .NET 10 / EF Core application using Npgsql with PostgreSQL 18. The application uses a singleton NpgsqlDataSource and scoped DbContext instances, with a maximum connection pool size of 30.
During a load test with 250 concurrent virtual users, HTTP p95 latency reaches approximately 1.6–2.2 seconds across baseline runs. A product creation request performs several database reads, followed by BeginTransactionAsync, additional quota and tenant checks, and SaveChangesAsync. Our application-level measurements show that BeginTransactionAsync can take hundreds of milliseconds under load. However, this timing does not distinguish waiting for an available pooled connection from the actual PostgreSQL transaction startup. *Question* What is the recommended way to measure these components separately with Npgsql and EF Core? Specifically: 1. Which Npgsql metrics expose pending connection requests and pool utilization? 2. Does EF Core's DbConnectionInterceptor.ConnectionOpenedAsync duration include waiting to acquire a pooled connection? 3. How can we correlate connection-open durations with BeginTransactionAsync latency? 4. Is there a recommended way to distinguish client-side pool contention from PostgreSQL lock waits without enabling sensitive SQL logging? We want to identify the real bottleneck before changing pool sizing or transaction behavior. The application is multi-tenant, and transaction integrity must be preserved. A sanitized minimal reproduction and runtime metrics can be supplied if needed.
