What precisely does DB_POSTGRESDB_POOL_SIZE control

Describe the problem/error/question

Quick overview of our setup:

  • 2 master containers
  • 8 n8n workers
  • Multiple workflow Postgres credentials pointing at multiple databases, with all databases hosted on the same Postgres server. The internal n8n database is also hosted on this server.
  • Workers and masters have DB_POSTGRESDB_POOL_SIZE=10
  • Workers have --concurrency=10
    .
    The issue we have is that the Postgres server is getting overwhelmed at peak times. I would like to understand exactly what DB_POSTGRESDB_POOL_SIZE=10 actually controls? Is this controlling just the pool size for the connections to the internal n8n database, or does it also the pooling used for the database connections configured within the workflow credentials? Lastly, what is the recommendation for the value of DB_POSTGRESDB_POOL_SIZE in relation to the concurrency setting? Do they need to be the same? Appreciate any insight you can provide.

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.)

Share the output returned by the last node

Information on your n8n setup

  • n8n version: 2.19.4
  • Database (default: SQLite): Postgres
  • n8n EXECUTIONS_PROCESS setting (default: own, main): Default
  • Running n8n via (Docker, npm, n8n cloud, desktop app): Kubernetes
  • Operating system:

Hey @David_Andrews, while you wait for a response, here are some things that might help:

Suggested resources

Automatically matched to your question.

Docs:

Forum:

@Yo_its_prakash, @Danilov_Vovka, @Wouter_Nigrini - you’ve helped with similar issues before, can you take a look?

Automatically suggested by n8n’s community bot. It’s a pilot - please share feedback here.

It controls the connection pool for n8n’s internal database only.

There is no strict requirement that these two values be the same, as they serve different purposes:

  • --concurrency (Worker Level): This dictates how many workflow executions a single worker can run simultaneously.
  • DB_POSTGRESDB_POOL_SIZE (App Level): This dictates how many connections the application uses to talk to its own “brain” (the internal DB).

Your current connection math looks like this:

  • Internal DB Connections: (2 Masters + 8 Workers) * 10 connections = 100 connections dedicated solely to n8n’s internal operations.
  • Workflow Connections: Each of your 8 workers can run 10 concurrent workflows. If those workflows all contain a Postgres node that executes a query, you could potentially have up to 80 (8 workers * 10 concurrency) additional active connections hitting your Postgres server at any given moment.

To mitigate the load on your Postgres server:

  1. Reduce DB_POSTGRESDB_POOL_SIZE: The default is often 2. Since you have 10 workers, having each worker hold 10 connections for the internal DB might be overkill unless you have extremely high internal DB contention. Lowering this to 2 or 5 across your workers will significantly reduce the “baseline” connection count.
  2. Check Postgres Node behavior: If your workflows are hitting the database very rapidly in a loop, ensure you aren’t opening more connections than necessary.
  3. Use a Connection Pooler: If you continue to scale, consider using a tool like PgBouncer in front of your Postgres server. This allows n8n to “think” it has many connections while PgBouncer manages a much smaller, more efficient pool of actual connections to the database.

Hi @David_Andrews
DB_POSTGRESDB_POOL_SIZE is a ceiling, not a reservation. Each process opens internal connections on demand up to that number and evicts idle ones after DB_POSTGRESDB_IDLE_CONNECTION_TIMEOUT (default 30000 ms), recycling the rest at DB_POSTGRESDB_MAX_CONNECTION_LIFETIME_MS, so a worker only sits near 10 while it is genuinely busy. All your databases are on the one server, so you can read the real split at peak rather than sizing from the worst case:

SELECT datname, state, count(*) FROM pg_stat_activity GROUP BY 1, 2 ORDER BY 3 DESC;

That shows which side is saturating you. How long the workflow connections stay open after a query finishes is set per node by “Delay Closing Idle Connection” in the Postgres node Options.

This is really helpful information - thank you. In addition to the above settings, there is also a setting within each Postgres credential which is titled “Maximum Number of Connections”. If we had for example 10 Postgres credentials, and each was set to the default value of 100, I assume the theoretical total number of connections could hit 1000 (i.e. 10 x 100) ? If my assumption is correct, would that 1000 maximum number of connections be per worker, or shared across all workers? Thanks in advance.

If you have 10 Postgres credentials and each is set to a “Maximum Number of Connections” of 100, then one single n8n process (one worker or one master) can theoretically open up to 1,000 connections (10 credentials * 100 connections each).

In your setup (2 masters, 8 workers), the connection limit is per worker.

In n8n’s Queue Mode, each worker is an independent process. When a worker picks up a task that uses a Postgres node, that worker is responsible for managing the connection pool for that specific credential.

  • Each Worker: Manages its own independent pool for every credential used in the workflows it executes.
  • Total Theoretical Connections: With 8 workers and 10 credentials (each capped at 100), your Postgres server could see up to 8,000 connections (8 workers * 10 credentials * 100 connections).