Atlaslog / Field Notes / Services & tile access
Field note · Services & tile access
Connection pool exhausted and every WMS returns 503
Quick answer
At the 9 a.m. peak all layers slow down and then the whole site returns 503 until GeoServer is restarted. The DBCP pool times out waiting for connections while PostgreSQL connections sit at max_connections.
Symptom
- org.apache.commons.dbcp2.ConnectionPoolTimeoutException: Timeout waiting for connection from pool.
- Every layer answers HTTP 503 with Retry-After: 120.
- pg_stat_activity shows the connection count at max_connections, with sessions staying active far longer than 30 seconds.
Checklist
- Group pg_stat_activity by usename and state to see who holds the connections.
- Find sessions where state is active and now() minus query_start exceeds 30 seconds.
- Check the datastore pool settings: maxActive, maxIdle and maxWait.
- Compare the sum of all workspace pools against the database max_connections.
- Distinguish leakage from an undersized pool: idle connections at zero with permanent waiting means leakage.
Fix
Raise database max_connections to 200 and size pools to match, such as 20 per datastore across three datastores with maxWait 10000 so requests fail fast instead of queueing forever. Close every Connection in a finally block and add a GiST index on roads.geom so a query stops holding a connection for tens of seconds.
Code
ERROR [geoserver.wms] -
org.geoserver.platform.ServiceException: Rendering process failed.
Caused by: org.apache.commons.dbcp2.ConnectionPoolTimeoutException:
Timeout waiting for connection from pool
at org.apache.commons.dbcp2.Datasource.waitForConnection(Datasource.java:1305)
HTTP/1.1 503 Service Unavailable
Retry-After: 120SELECT usename, state, count(*)
FROM pg_stat_activity
GROUP BY usename, state
ORDER BY count(*) DESC;
SELECT pid, now() - query_start AS duration, query
FROM pg_stat_activity
WHERE state = 'active' AND now() - query_start > interval '30 seconds';
Watch out
- Setting maxWait to -1, which makes requests wait indefinitely and turns one slow query into a total outage.
- Giving every layer its own datastore, so pool count grows linearly with layer count and blows the database limit.
English edition written for Atlaslog from the original Chinese field note. Code is unchanged and runs as-is.
Atlaslog (2026). Connection pool exhausted and every WMS returns 503. https://www.jingweizhi.com/en/cookbook/geoserver-db-pool-exhausted.html (accessed 2026-11-03).