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
Create a dedicated PostgreSQL database for n8n
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.
1-- Connect to PostgreSQL as a superuser2psql -U postgres34-- Create the database and user5CREATE DATABASE n8n_db;6CREATE USER n8n_user WITH ENCRYPTED PASSWORD 'your_secure_password_here';7GRANT ALL PRIVILEGES ON DATABASE n8n_db TO n8n_user;89-- Connect to the new database and grant schema privileges10\c n8n_db11GRANT 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.
Set n8n environment variables for PostgreSQL
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.
1# Required environment variables2export DB_TYPE=postgresdb3export DB_POSTGRESDB_HOST=localhost4export DB_POSTGRESDB_PORT=54325export DB_POSTGRESDB_DATABASE=n8n_db6export DB_POSTGRESDB_USER=n8n_user7export DB_POSTGRESDB_PASSWORD=your_secure_password_here89# Optional: connection pool size (default 10)10export DB_POSTGRESDB_POOL_SIZE=201112# Optional: SSL connection13# export DB_POSTGRESDB_SSL_REJECT_UNAUTHORIZED=false1415# Start n8n16n8n startExpected result: n8n starts and connects to PostgreSQL. The console shows 'Initializing n8n process' with no database errors.
Configure PostgreSQL with Docker Compose
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.
1version: '3.8'2services:3 postgres:4 image: postgres:16-alpine5 restart: always6 environment:7 POSTGRES_DB: n8n_db8 POSTGRES_USER: n8n_user9 POSTGRES_PASSWORD: your_secure_password_here10 volumes:11 - postgres_data:/var/lib/postgresql/data12 healthcheck:13 test: ['CMD-SHELL', 'pg_isready -U n8n_user -d n8n_db']14 interval: 5s15 timeout: 5s16 retries: 51718 n8n:19 image: docker.n8n.io/n8nio/n8n20 restart: always21 ports:22 - '5678:5678'23 environment:24 DB_TYPE: postgresdb25 DB_POSTGRESDB_HOST: postgres26 DB_POSTGRESDB_PORT: 543227 DB_POSTGRESDB_DATABASE: n8n_db28 DB_POSTGRESDB_USER: n8n_user29 DB_POSTGRESDB_PASSWORD: your_secure_password_here30 N8N_ENCRYPTION_KEY: your_encryption_key_here31 volumes:32 - n8n_data:/home/node/.n8n33 depends_on:34 postgres:35 condition: service_healthy3637volumes: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.
Add PostgreSQL credentials in the n8n editor for workflow use
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.
Use the Postgres node to query data in a workflow
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.
1-- Example: Select recent orders2SELECT id, customer_name, total, created_at3FROM orders4WHERE created_at > NOW() - INTERVAL '7 days'5ORDER BY created_at DESC6LIMIT 100;Expected result: The Postgres node returns the query results as an array of JSON objects, one per row.
Verify the connection and test common operations
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
1version: '3.8'23services:4 postgres:5 image: postgres:16-alpine6 restart: always7 environment:8 POSTGRES_DB: n8n_db9 POSTGRES_USER: n8n_user10 POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-changeme}11 volumes:12 - postgres_data:/var/lib/postgresql/data13 ports:14 - '5432:5432'15 healthcheck:16 test: ['CMD-SHELL', 'pg_isready -U n8n_user -d n8n_db']17 interval: 5s18 timeout: 5s19 retries: 52021 n8n:22 image: docker.n8n.io/n8nio/n8n23 restart: always24 ports:25 - '5678:5678'26 environment:27 - DB_TYPE=postgresdb28 - DB_POSTGRESDB_HOST=postgres29 - DB_POSTGRESDB_PORT=543230 - DB_POSTGRESDB_DATABASE=n8n_db31 - DB_POSTGRESDB_USER=n8n_user32 - DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD:-changeme}33 - DB_POSTGRESDB_POOL_SIZE=2034 - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}35 - N8N_PORT=567836 - WEBHOOK_URL=${WEBHOOK_URL:-http://localhost:5678}37 volumes:38 - n8n_data:/home/node/.n8n39 depends_on:40 postgres:41 condition: service_healthy4243volumes: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.
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.
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.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation