I’m running multiple n8n workers with several workflows hitting the same PostgreSQL database. Everything works fine at low traffic, but when concurrency increases, PostgreSQL starts reporting:
FATAL: remaining connection slots are reserved
Some workflows then fail even though the database itself isn’t under heavy CPU load.
I’m considering using PgBouncer and reducing the number of connections each worker can open, but I’m not sure how to decide where the actual limit should be.
For production, would you control this mainly through n8n concurrency, PostgreSQL max_connections, or PgBouncer?
Also, how would you monitor connection usage so a traffic spike doesn’t bring down unrelated workflows?
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.)
Lower the cap on the credential. Open your Postgres credential and turn down “Maximum Number of Connections”. If you take that number times your number of workers should stay under what Postgres allows, with some room left for n8n itself, because you don’t want n8n crashing.
Use fewer workers doing more each. Lots of small workers use more connections than a few bigger ones. Setting each worker’s concurrency to 5 or more works better than adding extra workers. Think of it like if u have 5 ppl at a resturant. It’s faster if u have 8 ppl serving than 2 taking every order.
Only reach for PgBouncer if you want/need more room. It can help however, it can break a few Postgres features , so tread carefully, I would say.
Give your heaviest workflows their own credential with a lower limit. That way a ton of traffic in one of them can’t use up the connections your other workflows need.
To keep an eye on it, you can run this in Postgres to see how many connections are open and who’s using them -
SELECT usename, application_name, state, count(*) FROM pg_stat_activity GROUP BY 1,2,3;
You can set an alert for when the total gets close to your Postgres limit, so you find out before workflows start failing, maybe a text or email alert.
Hi @Brooks_Kathy I would treat this as a connection management problem, not simply increase PostgreSQL’s max_connections.
First, control how much concurrency n8n can generate. If every worker can create many database connections, adding more workers can actually make the problem worse.
Then put PgBouncer in front of PostgreSQL so connections can be pooled and reused.
Also monitor the database directly:
SELECT
state,
COUNT(*) AS connections
FROM pg_stat_activity
GROUP BY state;
And check the configured limit:
SHOW max_connections;
I’d leave some PostgreSQL connections available for administration and other services instead of allowing n8n to consume everything.
The budgeting math that settled this for me: (workers x per-worker concurrency x peak connections per execution) has to stay under (max_connections - reserved - everything else that touches that DB, including admin sessions). Any number in that formula you don’t explicitly set is a number you’ve set by accident.
Concretely: cap concurrency per worker with N8N_CONCURRENCY_PRODUCTION_LIMIT rather than adding workers - queue mode applies it per worker, so “fewer bigger workers” is the stable shape - and put a Maximum Number of Connections cap on the Postgres credential itself so a burst of parallel executions can’t each grab a fresh connection.
Two Postgres-side guards that directly answer your “unrelated workflows going down” question: set statement_timeout on the role n8n connects as (a runaway query then releases its connection instead of holding a slot hostage for an hour), and set an aggressive connection acquisition timeout on the n8n side so a starved workflow fails fast and retries on its schedule instead of piling up half-open waits. PgBouncer is the right third layer once those are set - pooling on top of unbounded demand mostly changes which queue you’re waiting in.
And watch pg_stat_activity grouped by state across a full day before picking final numbers. The real peak is usually a scheduled-moment pileup - midnight jobs and hourly sweeps all firing together - not average traffic, and staggering the schedules is a free fix.
@Brooks_Kathy, is PostgreSQL getting filled up by n8n itself, or by the Postgres nodes in your workflows? I’d check that before changing the connection limit, since the fix depends on which one is using the connections.
If you can share a connection count grouped by database and user during a spike, that should make the next step clearer. No query text or credentials needed.