Skip to main content
RapidDev - Software Development Agency
n8n-tutorial

How to Connect n8n to PostgreSQL

Connect n8n to PostgreSQL by configuring the DB_TYPE and DB_POSTGRESDB_* environment variables, then use the Postgres node in your workflows to query, insert, and update data. This setup lets n8n use PostgreSQL as its internal database for executions and credentials, and also enables your workflows to interact with external PostgreSQL databases.

What you'll learn

  • How to configure n8n's internal database to use PostgreSQL
  • How to set up PostgreSQL credentials in the n8n editor
  • How to use the Postgres node to read and write data in workflows
  • How to optimize PostgreSQL performance for n8n workloads
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate6 min read15-20 minutesn8n 1.0+, PostgreSQL 12+March 2026RapidDev Engineering Team
TL;DR

Connect n8n to PostgreSQL by configuring the DB_TYPE and DB_POSTGRESDB_* environment variables, then use the Postgres node in your workflows to query, insert, and update data. This setup lets n8n use PostgreSQL as its internal database for executions and credentials, and also enables your workflows to interact with external PostgreSQL databases.

Using PostgreSQL with n8n for Storage and Workflows

By default, n8n uses SQLite for its internal database. While SQLite works for development, PostgreSQL is recommended for production because it handles concurrent access, supports larger datasets, and integrates with backup and monitoring tools. This tutorial covers two aspects: configuring n8n to use PostgreSQL as its internal database (for workflow definitions, credentials, and execution data), and using the Postgres node to query external PostgreSQL databases in your workflows.

Prerequisites

  • A running n8n instance (Docker, npm, or desktop)
  • A PostgreSQL 12+ server accessible from the n8n host
  • PostgreSQL connection details: host, port, database name, user, password
  • Basic familiarity with SQL and the n8n editor

Step-by-step guide

1

Create a dedicated PostgreSQL database for n8n

Connect to your PostgreSQL server and create a dedicated database and user for n8n. Avoid using the default postgres database for production. Grant the n8n user full privileges on the new database. n8n will create its own tables automatically on first startup.

typescript
1-- Connect to PostgreSQL as a superuser
2psql -U postgres
3
4-- Create the database and user
5CREATE DATABASE n8n_db;
6CREATE USER n8n_user WITH ENCRYPTED PASSWORD 'your_secure_password_here';
7GRANT ALL PRIVILEGES ON DATABASE n8n_db TO n8n_user;
8
9-- Connect to the new database and grant schema privileges
10\c n8n_db
11GRANT ALL ON SCHEMA public TO n8n_user;

Expected result: A new PostgreSQL database n8n_db exists with a dedicated user n8n_user that has full privileges.

2

Set n8n environment variables for PostgreSQL

Configure the environment variables that tell n8n to use PostgreSQL instead of SQLite. Set DB_TYPE to postgresdb and provide the connection details via the DB_POSTGRESDB_* variables. If you are running n8n with Docker, pass these as -e flags or in a docker-compose.yml file. For npm installations, export them in your shell or add them to a .env file.

typescript
1# Required environment variables
2export DB_TYPE=postgresdb
3export DB_POSTGRESDB_HOST=localhost
4export DB_POSTGRESDB_PORT=5432
5export DB_POSTGRESDB_DATABASE=n8n_db
6export DB_POSTGRESDB_USER=n8n_user
7export DB_POSTGRESDB_PASSWORD=your_secure_password_here
8
9# Optional: connection pool size (default 10)
10export DB_POSTGRESDB_POOL_SIZE=20
11
12# Optional: SSL connection
13# export DB_POSTGRESDB_SSL_REJECT_UNAUTHORIZED=false
14
15# Start n8n
16n8n start

Expected result: n8n starts and connects to PostgreSQL. The console shows 'Initializing n8n process' with no database errors.

3

Configure PostgreSQL with Docker Compose

If you are running n8n on Docker, create a docker-compose.yml file that defines both the n8n service and a PostgreSQL service. This keeps everything in one configuration file and ensures the database is available before n8n starts. Use named volumes for data persistence.

typescript
1version: '3.8'
2services:
3 postgres:
4 image: postgres:16-alpine
5 restart: always
6 environment:
7 POSTGRES_DB: n8n_db
8 POSTGRES_USER: n8n_user
9 POSTGRES_PASSWORD: your_secure_password_here
10 volumes:
11 - postgres_data:/var/lib/postgresql/data
12 healthcheck:
13 test: ['CMD-SHELL', 'pg_isready -U n8n_user -d n8n_db']
14 interval: 5s
15 timeout: 5s
16 retries: 5
17
18 n8n:
19 image: docker.n8n.io/n8nio/n8n
20 restart: always
21 ports:
22 - '5678:5678'
23 environment:
24 DB_TYPE: postgresdb
25 DB_POSTGRESDB_HOST: postgres
26 DB_POSTGRESDB_PORT: 5432
27 DB_POSTGRESDB_DATABASE: n8n_db
28 DB_POSTGRESDB_USER: n8n_user
29 DB_POSTGRESDB_PASSWORD: your_secure_password_here
30 N8N_ENCRYPTION_KEY: your_encryption_key_here
31 volumes:
32 - n8n_data:/home/node/.n8n
33 depends_on:
34 postgres:
35 condition: service_healthy
36
37volumes:
38 postgres_data:
39 n8n_data:

Expected result: Running docker compose up -d starts PostgreSQL first, waits for the health check, then starts n8n connected to the database.

4

Add PostgreSQL credentials in the n8n editor for workflow use

To use the Postgres node in your workflows (separate from n8n's internal database), you need to create a Postgres credential in the n8n editor. Go to Settings, then Credentials, then click Add Credential. Select Postgres and enter the connection details for the database you want to query. This can be the same database as n8n's internal database or a different one entirely.

Expected result: A Postgres credential appears in your credentials list and can be selected in any Postgres node.

5

Use the Postgres node to query data in a workflow

Add a Postgres node to your workflow. Select the credential you created. Choose the operation: Execute Query for custom SQL, Insert for adding rows, Update for modifying rows, or Select for simple queries. For Execute Query, write your SQL in the Query field. Use n8n expressions to inject dynamic values from upstream nodes.

typescript
1-- Example: Select recent orders
2SELECT id, customer_name, total, created_at
3FROM orders
4WHERE created_at > NOW() - INTERVAL '7 days'
5ORDER BY created_at DESC
6LIMIT 100;

Expected result: The Postgres node returns the query results as an array of JSON objects, one per row.

6

Verify the connection and test common operations

Test the full setup by creating a simple workflow: Manual Trigger then Postgres node (Execute Query: SELECT NOW()). Execute the workflow. If the Postgres node returns the current timestamp, the connection is working. Next, test an INSERT and a SELECT to verify read/write access. Check the n8n execution log to confirm no connection pool warnings.

Expected result: The workflow executes successfully and the Postgres node returns the current timestamp from the database.

Complete working example

docker-compose.yml
1version: '3.8'
2
3services:
4 postgres:
5 image: postgres:16-alpine
6 restart: always
7 environment:
8 POSTGRES_DB: n8n_db
9 POSTGRES_USER: n8n_user
10 POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-changeme}
11 volumes:
12 - postgres_data:/var/lib/postgresql/data
13 ports:
14 - '5432:5432'
15 healthcheck:
16 test: ['CMD-SHELL', 'pg_isready -U n8n_user -d n8n_db']
17 interval: 5s
18 timeout: 5s
19 retries: 5
20
21 n8n:
22 image: docker.n8n.io/n8nio/n8n
23 restart: always
24 ports:
25 - '5678:5678'
26 environment:
27 - DB_TYPE=postgresdb
28 - DB_POSTGRESDB_HOST=postgres
29 - DB_POSTGRESDB_PORT=5432
30 - DB_POSTGRESDB_DATABASE=n8n_db
31 - DB_POSTGRESDB_USER=n8n_user
32 - DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD:-changeme}
33 - DB_POSTGRESDB_POOL_SIZE=20
34 - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
35 - N8N_PORT=5678
36 - WEBHOOK_URL=${WEBHOOK_URL:-http://localhost:5678}
37 volumes:
38 - n8n_data:/home/node/.n8n
39 depends_on:
40 postgres:
41 condition: service_healthy
42
43volumes:
44 postgres_data:
45 n8n_data:

Common mistakes when connecting n8n to PostgreSQL

Why it's a problem: Forgetting to set N8N_ENCRYPTION_KEY, causing credentials to become unreadable after restart

How to avoid: Generate a random encryption key with openssl rand -hex 32 and set it as N8N_ENCRYPTION_KEY. Store it securely.

Why it's a problem: Using the same credentials for n8n's internal database and workflow queries without realizing they can be different

How to avoid: n8n's internal database (DB_POSTGRESDB_* env vars) and Postgres node credentials (configured in the editor) are independent. Use separate databases if needed.

Why it's a problem: Not granting schema privileges to the n8n user

How to avoid: Run GRANT ALL ON SCHEMA public TO n8n_user on the n8n database. n8n needs to create tables on first startup.

Why it's a problem: Setting DB_POSTGRESDB_HOST to localhost inside Docker when PostgreSQL runs in a separate container

How to avoid: Use the Docker service name (e.g., postgres) as the host. localhost inside a container refers to the container itself.

Best practices

  • Always use a dedicated PostgreSQL user for n8n instead of the postgres superuser
  • Set N8N_ENCRYPTION_KEY explicitly so credentials can be decrypted after container restarts
  • Use PostgreSQL 14 or later for best performance with n8n's query patterns
  • Set DB_POSTGRESDB_POOL_SIZE to 20 for production workloads (default is 10)
  • Enable SSL for remote PostgreSQL connections with DB_POSTGRESDB_SSL_REJECT_UNAUTHORIZED
  • Back up the PostgreSQL database regularly — it contains all workflows, credentials, and execution data
  • Monitor connection pool usage with N8N_METRICS=true and a Prometheus/Grafana setup
  • Use health checks in Docker Compose to ensure PostgreSQL is ready before n8n starts

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

How do I configure n8n to use PostgreSQL instead of SQLite as its internal database? I need the environment variables, Docker Compose setup, and instructions for creating the database.

n8n Prompt

Create a docker-compose.yml for n8n with PostgreSQL as the backend database. Include health checks, named volumes, and all required DB_POSTGRESDB_* environment variables.

Frequently asked questions

Can n8n use PostgreSQL and SQLite at the same time?

No. n8n uses one database backend at a time, determined by the DB_TYPE environment variable. Set it to postgresdb for PostgreSQL or leave it unset for the default SQLite.

How do I migrate from SQLite to PostgreSQL?

n8n provides a migration command: n8n export:workflow --all --output=workflows.json to export workflows, then set the PostgreSQL environment variables, start n8n (it creates the schema), and import with n8n import:workflow --input=workflows.json. Credentials and executions require separate migration.

What PostgreSQL version does n8n require?

n8n officially supports PostgreSQL 12 and later. PostgreSQL 14 or 16 is recommended for production for better performance and security patches.

Does n8n support connection pooling with tools like PgBouncer?

Yes. Point the DB_POSTGRESDB_HOST to your PgBouncer instance. Use session pooling mode for compatibility with n8n's transaction patterns.

How much disk space does n8n's PostgreSQL database use?

This depends on execution volume. Each execution stores input/output data. A typical setup with 10,000 daily executions uses 1-5 GB per month. Use n8n's pruning settings (EXECUTIONS_DATA_MAX_AGE) to limit data retention.

Can RapidDev help set up a production n8n deployment with PostgreSQL?

Yes. RapidDev can configure a production-grade n8n deployment with PostgreSQL, including Docker Compose setup, SSL, backups, monitoring, and performance tuning.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.