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

How to Use n8n with Self-Hosted PostgreSQL or MySQL Databases

n8n supports PostgreSQL as its recommended backend database and MySQL as a deprecated alternative. Set the DB_TYPE environment variable to postgresdb and provide connection details via DB_POSTGRESDB_HOST, DB_POSTGRESDB_PORT, DB_POSTGRESDB_DATABASE, DB_POSTGRESDB_USER, and DB_POSTGRESDB_PASSWORD. This replaces the default SQLite and enables production-grade reliability with proper backup and scaling options.

What you'll learn

  • How to configure n8n to use PostgreSQL as its backend database
  • How to set all required environment variables for database connectivity
  • How to migrate existing data from SQLite to PostgreSQL
  • How to verify the database connection and troubleshoot common issues
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner7 min read20-30 minutesn8n 1.0+, npm and Docker installationsMarch 2026RapidDev Engineering Team
TL;DR

n8n supports PostgreSQL as its recommended backend database and MySQL as a deprecated alternative. Set the DB_TYPE environment variable to postgresdb and provide connection details via DB_POSTGRESDB_HOST, DB_POSTGRESDB_PORT, DB_POSTGRESDB_DATABASE, DB_POSTGRESDB_USER, and DB_POSTGRESDB_PASSWORD. This replaces the default SQLite and enables production-grade reliability with proper backup and scaling options.

How to Use n8n with Self-Hosted Databases

By default, n8n uses SQLite to store workflows, credentials, and execution data. While SQLite works well for development and small deployments, production environments benefit from using PostgreSQL or MySQL as the backend database. An external database provides better concurrency, easier backups, replication support, and the ability to run multiple n8n instances against the same database. PostgreSQL is the recommended choice as MySQL support is deprecated.

Prerequisites

  • A running PostgreSQL 13+ server accessible from your n8n host
  • A dedicated database and user created for n8n
  • n8n installed via npm or Docker
  • Basic knowledge of environment variables and database connection strings
  • Terminal or SSH access to your n8n server

Step-by-step guide

1

Create a PostgreSQL database and user for n8n

Log in to your PostgreSQL server and create a dedicated database and user for n8n. Using a separate user with limited permissions follows security best practices and prevents n8n from affecting other databases on the same server. Grant the user full access to the n8n database only.

typescript
1-- Connect to PostgreSQL as the admin user
2-- psql -U postgres
3
4-- Create a dedicated user for n8n
5CREATE USER n8n_user WITH PASSWORD 'your_secure_password_here';
6
7-- Create the n8n database
8CREATE DATABASE n8n_db OWNER n8n_user;
9
10-- Grant all privileges on the database to the n8n user
11GRANT ALL PRIVILEGES ON DATABASE n8n_db TO n8n_user;
12
13-- Verify the database was created
14\l

Expected result: A new database called n8n_db and a user called n8n_user are created in PostgreSQL. The user has full ownership of the database.

2

Set environment variables for npm installations

For npm installations, set the database connection environment variables before starting n8n. You can set them in your shell profile, a .env file, or your systemd service file. The required variables are DB_TYPE, DB_POSTGRESDB_HOST, DB_POSTGRESDB_PORT, DB_POSTGRESDB_DATABASE, DB_POSTGRESDB_USER, and DB_POSTGRESDB_PASSWORD.

typescript
1# Set environment variables in your shell or .env file
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: Set the schema (default is 'public')
10export DB_POSTGRESDB_SCHEMA=public
11
12# Optional: Enable SSL for remote databases
13export DB_POSTGRESDB_SSL_ENABLED=true
14
15# Start n8n with the database configuration
16n8n start

Expected result: n8n starts and connects to the PostgreSQL database. On first startup, it automatically creates all required tables and indexes.

3

Set environment variables for Docker installations

For Docker installations, pass the environment variables when creating the container using the -e flag or a docker-compose.yml file. The Docker approach is the most common for production deployments. Make sure the n8n container can reach the PostgreSQL server over the network.

typescript
1# Docker run command with PostgreSQL configuration
2docker run -d \
3 --name n8n \
4 -p 5678:5678 \
5 -e DB_TYPE=postgresdb \
6 -e DB_POSTGRESDB_HOST=your-postgres-host \
7 -e DB_POSTGRESDB_PORT=5432 \
8 -e DB_POSTGRESDB_DATABASE=n8n_db \
9 -e DB_POSTGRESDB_USER=n8n_user \
10 -e DB_POSTGRESDB_PASSWORD=your_secure_password_here \
11 -v n8n_data:/home/node/.n8n \
12 docker.n8n.io/n8nio/n8n
13
14# Or use docker-compose.yml (see complete code below)

Expected result: The n8n Docker container starts and connects to PostgreSQL. The n8n logs show a successful database connection message.

4

Verify the database connection

After starting n8n with the PostgreSQL configuration, verify the connection is working. Check the n8n logs for any database connection errors. Then open the n8n editor in your browser and create a test workflow to confirm data is being stored in PostgreSQL. You can also query the PostgreSQL database directly to see the tables n8n created.

typescript
1# Check n8n logs for database connection status
2# npm installation
3n8n start 2>&1 | head -20
4
5# Docker installation
6docker logs n8n
7
8# Verify tables were created in PostgreSQL
9psql -U n8n_user -d n8n_db -c "\dt"
10
11# Expected tables include:
12# workflow_entity
13# credentials_entity
14# execution_entity
15# webhook_entity
16# tag_entity

Expected result: n8n logs show no database errors. The PostgreSQL database contains n8n tables. Creating and saving a workflow in the editor writes data to the PostgreSQL database.

5

Migrate existing data from SQLite to PostgreSQL (optional)

If you have existing workflows and credentials in SQLite that you want to keep, export them before switching databases. Use the n8n CLI to export workflows and credentials to JSON files, then import them after configuring the PostgreSQL database. This approach is safer than trying to migrate the raw database files.

typescript
1# Step 1: Export workflows from SQLite (before changing DB_TYPE)
2n8n export:workflow --all --output=./workflows-backup.json
3
4# Step 2: Export credentials
5n8n export:credentials --all --output=./credentials-backup.json
6
7# Step 3: Switch to PostgreSQL (set the DB_TYPE and connection vars)
8export DB_TYPE=postgresdb
9export DB_POSTGRESDB_HOST=localhost
10export DB_POSTGRESDB_PORT=5432
11export DB_POSTGRESDB_DATABASE=n8n_db
12export DB_POSTGRESDB_USER=n8n_user
13export DB_POSTGRESDB_PASSWORD=your_secure_password_here
14
15# Step 4: Start n8n to create the PostgreSQL schema
16n8n start &
17sleep 10
18
19# Step 5: Import workflows into PostgreSQL
20n8n import:workflow --input=./workflows-backup.json
21
22# Step 6: Import credentials
23n8n import:credentials --input=./credentials-backup.json

Expected result: All workflows and credentials from your SQLite installation are now available in the PostgreSQL-backed n8n instance.

Complete working example

docker-compose.yml
1version: '3.8'
2
3services:
4 n8n:
5 image: docker.n8n.io/n8nio/n8n
6 container_name: n8n
7 restart: unless-stopped
8 ports:
9 - '5678:5678'
10 environment:
11 # Database configuration
12 - DB_TYPE=postgresdb
13 - DB_POSTGRESDB_HOST=postgres
14 - DB_POSTGRESDB_PORT=5432
15 - DB_POSTGRESDB_DATABASE=n8n_db
16 - DB_POSTGRESDB_USER=n8n_user
17 - DB_POSTGRESDB_PASSWORD=${N8N_DB_PASSWORD}
18 - DB_POSTGRESDB_SCHEMA=public
19 # n8n configuration
20 - N8N_HOST=localhost
21 - N8N_PORT=5678
22 - N8N_PROTOCOL=http
23 - WEBHOOK_URL=http://localhost:5678/
24 # Execution data retention (days)
25 - EXECUTIONS_DATA_MAX_AGE=168
26 - EXECUTIONS_DATA_PRUNE=true
27 volumes:
28 - n8n_data:/home/node/.n8n
29 depends_on:
30 postgres:
31 condition: service_healthy
32
33 postgres:
34 image: postgres:16-alpine
35 container_name: n8n-postgres
36 restart: unless-stopped
37 environment:
38 - POSTGRES_DB=n8n_db
39 - POSTGRES_USER=n8n_user
40 - POSTGRES_PASSWORD=${N8N_DB_PASSWORD}
41 volumes:
42 - postgres_data:/var/lib/postgresql/data
43 healthcheck:
44 test: ['CMD-SHELL', 'pg_isready -U n8n_user -d n8n_db']
45 interval: 10s
46 timeout: 5s
47 retries: 5
48
49volumes:
50 n8n_data:
51 postgres_data:

Common mistakes when using n8n with Self-Hosted PostgreSQL or MySQL Databases

Why it's a problem: Using localhost as the PostgreSQL host in Docker when PostgreSQL runs on the host machine

How to avoid: Use the Docker host IP (host.docker.internal on Mac/Windows, or the host network IP on Linux) instead of localhost. In docker-compose, use the service name as the hostname.

Why it's a problem: Forgetting to create the database before starting n8n

How to avoid: n8n creates tables and indexes automatically but does not create the database itself. Create the database and user in PostgreSQL before starting n8n with the database configuration.

Why it's a problem: Losing credential encryption keys when switching databases

How to avoid: The encryption key is stored in the .n8n directory (config file). Ensure the same .n8n directory is mounted or accessible after switching databases. Without the encryption key, imported credentials cannot be decrypted.

Why it's a problem: Not enabling execution data pruning, causing the database to grow without limit

How to avoid: Set EXECUTIONS_DATA_PRUNE=true and EXECUTIONS_DATA_MAX_AGE=168 (hours) to automatically delete old execution data. Without pruning, the execution_entity table can grow to gigabytes.

Best practices

  • Always use PostgreSQL for production deployments — MySQL support is deprecated and may be removed in future n8n versions
  • Use a dedicated database user with access only to the n8n database, not a superuser account
  • Enable SSL for database connections when PostgreSQL runs on a different server
  • Set up automated PostgreSQL backups using pg_dump on a cron schedule
  • Configure execution data pruning with EXECUTIONS_DATA_PRUNE and EXECUTIONS_DATA_MAX_AGE to prevent the database from growing unbounded
  • Use Docker Compose with health checks to ensure PostgreSQL is ready before n8n starts
  • Store database passwords in environment variables or secrets management, never in configuration files committed to version control
  • Monitor PostgreSQL disk usage and performance, especially the execution_entity table which grows quickly

Still stuck?

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

ChatGPT Prompt

I want to move my n8n installation from SQLite to PostgreSQL without losing my existing workflows and credentials. What is the step-by-step process including data export, database setup, and import?

n8n Prompt

Create a docker-compose.yml file that runs n8n with a PostgreSQL database, includes health checks, SSL configuration, and execution data pruning settings.

Frequently asked questions

Should I use PostgreSQL or MySQL for n8n?

Use PostgreSQL. MySQL support in n8n is deprecated and may be removed in future versions. PostgreSQL provides better performance, more reliable migrations, and is the officially recommended database for production n8n deployments.

Can I use a managed PostgreSQL service like AWS RDS or DigitalOcean Managed Databases?

Yes. Set the DB_POSTGRESDB_HOST to your managed database endpoint, provide the port, credentials, and enable SSL with DB_POSTGRESDB_SSL_ENABLED=true. Managed databases handle backups and replication automatically.

Will switching from SQLite to PostgreSQL require downtime?

Yes. You need to stop n8n, export data, configure the new database, start n8n against PostgreSQL, and then import the data. Plan for 15-30 minutes of downtime depending on the amount of data.

How much disk space does n8n use in PostgreSQL?

Workflow and credential data is small, typically under 100MB. Execution history is the main space consumer. Without pruning, it can grow to several gigabytes. Enable EXECUTIONS_DATA_PRUNE to control this.

Can multiple n8n instances share the same PostgreSQL database?

Yes, but only in queue mode. Running multiple n8n instances in regular mode against the same database causes execution conflicts. Enable queue mode with EXECUTIONS_MODE=queue for multi-instance deployments.

What happens if the PostgreSQL connection is lost while n8n is running?

n8n attempts to reconnect automatically. Active workflow executions may fail with database connection errors. Once the database is back online, n8n resumes normal operation. Check n8n logs for connection status.

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.