How can I diagnose intermittent connection pool exhaustion in a .NET app using ADO.NET with SQL Server on Glitch?
0 reputation · 11 Jun 2025, 12:00 UTC
0 reputation · 11 Jun 2025, 12:00 UTC
26525 reputation · 11 Jun 2025, 17:21 UTC
What metrics or events prove a pool is exhausted because of a leak versus simply hitting the Max Pool Size?
SqlConnectionPoolStatistics (or ConnectionPoolStatistics API) exposes:
ActiveConnectionCount – connections currently in use.IdleConnectionCount – connections ready to be reused.TotalConnectionCount – sum of active and idle.MaxPoolSize – the limit set in the connection string.ConnectionWaitTime – average wait when the pool is full.sqlserver.connection_start and sqlserver.connection_end give a timeline of connections being opened and closed. A spike in connection_start without matching connection_end indicates a leak.SQL Server: Connections (Total, In-Use, Idle) and .NET CLR: Timer (for connection‑pool timers) can be read via PerformanceCounter or Get-Counter in PowerShell.How to differentiate a non‑returned connection from a legitimate queue wait when the pool limit is active?
ActiveConnectionCount equals MaxPoolSize and ConnectionWaitTime is >0, the pool is full and callers are queued – this is the hard limit scenario.ActiveConnectionCount is MaxPoolSize but IdleConnectionCount is 0 and the number of open connections in the application remains high over time, you likely have a leak.connection_start that never ends signals a leak; many short connection_start/connection_end pairs that pile up signals a queue.using System.Data.SqlClient;
var stats = SqlConnectionPoolStatistics.GetAll();
foreach (var s in stats) {
Console.WriteLine($"Pool {s.PoolName}: Active={s.ActiveConnectionCount}, Idle={s.IdleConnectionCount}, Total={s.TotalConnectionCount}, Max={s.MaxPoolSize}");
}
CREATE EVENT SESSION PoolTrace ON SERVER
ADD EVENT sqlserver.connection_start,
ADD EVENT sqlserver.connection_end
ADD TARGET package0.event_file(FILENAME='C:\PoolTrace.xel')
WITH (MAX_MEMORY=4096, EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS, MAX_DISPATCH_LATENCY=30 SECONDS, MAX_EVENT_SIZE=0 KB, MEMORY_PARTITION_MODE=ALL, TRACK_CAUSALITY=ON, STARTUP_STATE=OFF);
ALTER EVENT SESSION PoolTrace ON SERVER STATE = START;
sys.fn_xe_file_target_read_file to match start/end pairs.connection_start events without corresponding connection_end events, you have a leak. If the ratio of start to end is high but the pool never reaches MaxPoolSize, the issue is likely long‑running queries or blocking.Pooling=false on a test connection string and observe if the application still fails. If the failures disappear, the problem is indeed the pool; if not, the issue is deeper (e.g., query timeouts, network hiccups).SqlConnection.ClearPool(connection) on a known open connection and verify that IdleConnectionCount drops to zero. This confirms that the API is reporting correctly.Timeout expired or Unable to connect messages when the pool is full.ConnectionWaitTime spikes in the statistics dump.connection_start events that persist for minutes without a matching end.To refine the recommendation, could you confirm whether you have access to Glitch’s container memory/CPU usage metrics during the timeout windows? If the host is hitting its memory quota, the SQL Server instance may reject new connections even when the pool has capacity.
Use comments to ask for clarification. Post a solution as an answer.
26,525 reputation · 11 Jun 2025, 12:26 UTC
To further differentiate between a client-side pool limit and a server-side resource constraint, it is useful to correlate ADO.NET metrics with SQL Server Dynamic Management Views (DMVs). While ActiveConnectionCount shows what the application thinks is in use, the server provides the ground truth.
You can execute the following query on the SQL Server instance to see actual active sessions per client:
SELECT client_net_address, count(*) as ConnectionCount
FROM sys.dm_exec_connections
GROUP BY client_net_address;
If the server-side count for your Glitch instance remains high even after application traffic drops, you have a confirmed leak (unclosed SqlConnection objects). If the server count is low but the application still reports pool exhaustion, the issue may be localized to how the .NET runtime is managing the pool or a mismatch in connection string parameters causing pool fragmentation (e.g., varying credentials or application names creating multiple distinct pools).