MongoDB: connection pool timeout waiting for available connection
Fix MongoDB connection pool timeouts by sizing maxPoolSize, finding connection leaks, and matching pool size to workload concurrency.
Symptoms
- MongoServerSelectionError or MongoWaitQueueTimeoutError: Timed out while waiting for a connection
- Requests queue under load and then fail
- The driver logs wait queue timeouts only at peak
Possible causes
- maxPoolSize is smaller than the concurrent operation count
- Connections are checked out and not released due to a leaked cursor or session
- A slow query holds a connection for a long time
- Many application instances multiply the total demand against the server limit
Diagnosis steps
Check pool metrics and wait queue times
client.on("connectionPoolCreated", ...) and pool statsInterpretation
Consistently waiting for a connection means the pool is saturated.
Look for operations that never complete
Interpretation
A leaked cursor or uninterruptible query holds a connection indefinitely.
Compare total connections across instances to the server limit
Interpretation
Many instances each with a large pool can exceed maxIncomingConnections on the server.
Root cause
The driver maintains a connection pool; an operation checks out a connection and returns it when done. If the pool is smaller than the number of simultaneous operations, waiters time out. Leaked connections or slow operations make the pool effectively smaller.
Fix
Increase maxPoolSize to match concurrent demand, and ensure cursors, sessions, and transactions are closed so connections return to the pool. Optimise slow queries that hold connections, and account for the total across instances so the aggregate stays under the server connection limit.
Verify the fix
Re-run the load; wait queue timeouts disappear, pool statistics show connections cycling rather than pinned, and p95 latency stays stable.
Symptoms
Under load the driver reports Timed out while waiting for a connection or a server selection error. It clears when traffic drops, which marks a pool sizing or leak problem.
Diagnosis
Watch pool events and size against concurrency:
const client = new MongoClient(uri, {
maxPoolSize: 50,
waitQueueTimeoutMS: 5000,
});
client.on('connectionPoolCreated', (e) => console.log(e));
If waiters always exceed free connections, the pool is too small or connections are pinned.
Fix
Size the pool and release resources:
const cursor = coll.find({});
for await (const doc of cursor) { /* ... */ }
await cursor.close(); // return the connection
await session.endSession(); // close sessions
Keep the aggregate maxPoolSize * instances under the server limit.
Verification
Re-run the load test; pool stats show connections returning, wait-queue timeouts stop, and latency remains stable instead of climbing then failing.
Additional Notes
Pool exhaustion is often a symptom of operations that never release their connection rather than of genuinely insufficient capacity. Cursors, sessions, and transactions each borrow a connection, and one left open holds it for the life of the process. Comparing active connections to in-flight operations reveals whether the pool is truly undersized or merely leaking, and combining pool size across every application instance against the server limit avoids a different failure where the aggregate exceeds what the server accepts. Wait-queue timeouts are the clearest signal that demand outstrips capacity.