Hi guys
I’m running n8n with multiple workers, and as concurrency increases, I’m starting to think about PostgreSQL connection management.
My architecture is roughly:Load Balancer
↓
Multiple n8n Workers
↓
PostgreSQL
My concern is that if every worker opens multiple database connections, the database could eventually hit its connection limit, affecting workflow performance and stability.
I’m considering using a connection pooler like PgBouncer, but I’d like to understand how others manage this in production.
For those running PostgreSQL with high-concurrency n8n deployments:
How do you decide on the right max_connections setting?
Do you use a connection pooler like PgBouncer, or is PostgreSQL’s default behavior enough?
How do you monitor for connection exhaustion before it becomes a problem?
Have you found that increasing worker count or optimizing queries has a bigger impact on overall database performance?
Describe the problem/error/question
What is the error message (if any)?
Please share your workflow
(Select the nodes on your canvas and use the keyboard shortcuts CMD+C/CTRL+C and CMD+V/CTRL+V to copy and paste the workflow.)
Hi @Keira_Becky A good approach is to optimize connection usage before increasing the connection limit.
Recommended approach
Instead of continuously raising max_connections, use a connection pooler like PgBouncer to reuse existing connections efficiently.
n8n Workers
↓
PgBouncer
↓
PostgreSQL
This reduces connection overhead and helps PostgreSQL handle higher concurrency more efficiently.
Best practices
Use connection pooling for multiple workers
Set max_connections based on your server’s CPU and memory
Monitor active, idle, and waiting connections
Optimize slow queries before adding more workers
Keep an eye on: Active connections
Idle connections
Connection wait time
Query latency
CPU and memory usage
In production, connection pooling and query optimization usually provide better scalability than simply increasing PostgreSQL’s connection limit.
In a standard n8n deployment, the formula isn’t just workers * 1. Each worker process can maintain a pool of connections.
The Calculation Logic:
Main Instance: Needs a few connections for the UI, API, and scheduler.
Workers: Each worker process typically maintains a small pool. If you have 10 workers and each allows a pool of 10, you’re at 100 connections just for workers.
Overhead: Postgres allocates memory for each connection (roughly 2-10MB depending on work_mem). Setting max_connections too high (e.g., 5000) without sufficient RAM will cause the OS to kill Postgres via the OOM killer.
Recommendation: Start with max_connections = 200-500 for mid-sized deployments. If you exceed this, do not simply keep increasing the number; move to a pooler.
PgBouncer is for high-concurrency production environments.
PostgreSQL’s default behavior is “one process per connection,” which is expensive. PgBouncer acts as a lightweight proxy that manages a pool of “real” connections to the DB while allowing thousands of “virtual” connections from n8n workers.
Hi @Keira_Becky
The per-process lever is DB_POSTGRESDB_POOL_SIZE, which defaults to 2, so the footprint is roughly (main processes + workers + webhook processors) times that value, and you size the database around that figure instead of estimating from worker count. Raise it per process only when workers are actually waiting on the pool.
Scale by running fewer workers at higher concurrency rather than many workers at low concurrency, n8n recommends 5 or higher per worker because a large number of low-concurrency workers exhausts the connection pool and causes delays and failures:
It depends on your workload, but for most high-concurrency applications, transaction pooling is often preferred because it allows connections to be reused more efficiently and supports a larger number of concurrent clients.
Session pooling can be a better choice if your application relies on session-specific features, such as temporary tables or session variables, since each client keeps the same database connection for the entire session.
Before choosing a mode, I’d test it in a staging environment and verify that your n8n workflows don’t depend on session-specific behavior. Then monitor connection usage, query latency, and overall throughput to confirm it’s performing as expected.
In general, the best choice depends on how your application uses database connections, so it’s worth validating with production-like workloads before deploying.