PostgreSQL Connections on a VPS: Build a Budget Before Adding Workers
Prevent connection exhaustion by counting every consumer and leaving room for releases and administration.
PostgreSQL connection exhaustion often appears immediately after an application scales its workers. Each new process or pool may reserve additional connections, even when request volume changes only slightly. On a VPS, the database also shares a finite memory and CPU budget with other services. Count possible consumers before raising the server limit. A larger limit can remove a symptom while allowing more concurrent work than the database can handle usefully.
Count all connection owners
List web processes, thread pools, background workers, scheduled tasks, reporting tools, migrations, and administrative sessions. For every client pool, record its minimum, maximum, and lifetime behavior. An illustrative application with four processes and a pool maximum of ten can request forty connections before workers or reporting tools are counted. Treat this as an upper bound to investigate, not an assumption that every connection is always active. Verify how your particular driver and framework create and release connections.
Reserve operational headroom
Deployments can temporarily run old and new application processes together. Maintenance commands and emergency investigation also need access during a busy period. Include those scenarios in the budget and preserve PostgreSQL's intended administrative reserves. The PostgreSQL connection configuration reference explains maximum and reserved connections and notes that increasing the maximum affects resource allocation. Review the version matching your server, since configuration features and role behavior can differ across major versions.
Distinguish connections from active work
An idle connection consumes a slot but differs from an active query or a transaction left open. Observe connection state and transaction age while the application is busy. A large pool can make an application appear prepared for bursts while leaving most slots unused. Conversely, a small number of long transactions can hold locks that block many other requests. Investigate the pattern before choosing between reducing pool sizes, correcting transaction handling, or adding an appropriate connection pooler.
Check pooling compatibility
A pooler can reduce direct server connections, but its mode changes how application sessions map to database sessions. Review compatibility with session state, prepared statements, advisory locks, and other features your application uses. Test the real workflow under the chosen pooler rather than assuming all SQL behaves identically. Keep connection acquisition timeouts bounded and visible to application monitoring. If requests wait in a pool, that delay should be measured separately from query execution so you can identify the limiting layer.
Exercise a deployment under load
In staging, run representative traffic and perform the normal release process while recording peak connections, waiting time, errors, and memory. Include a scheduled job and an administrative query. Confirm that the chosen budget survives overlap without consuming every available slot. Revisit it when worker counts change, and use the shared application and database guide to account for the rest of the machine. Compare LayerOne resources only after you understand whether the constraint is connections, useful query concurrency, or total memory.