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
Create a PostgreSQL database and user for n8n
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.
1-- Connect to PostgreSQL as the admin user2-- psql -U postgres34-- Create a dedicated user for n8n5CREATE USER n8n_user WITH PASSWORD 'your_secure_password_here';67-- Create the n8n database8CREATE DATABASE n8n_db OWNER n8n_user;910-- Grant all privileges on the database to the n8n user11GRANT ALL PRIVILEGES ON DATABASE n8n_db TO n8n_user;1213-- Verify the database was created14\lExpected 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.
Set environment variables for npm installations
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.
1# Set environment variables in your shell or .env file2export 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: Set the schema (default is 'public')10export DB_POSTGRESDB_SCHEMA=public1112# Optional: Enable SSL for remote databases13export DB_POSTGRESDB_SSL_ENABLED=true1415# Start n8n with the database configuration16n8n startExpected result: n8n starts and connects to the PostgreSQL database. On first startup, it automatically creates all required tables and indexes.
Set environment variables for Docker installations
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.
1# Docker run command with PostgreSQL configuration2docker 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/n8n1314# 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.
Verify the database connection
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.
1# Check n8n logs for database connection status2# npm installation3n8n start 2>&1 | head -2045# Docker installation6docker logs n8n78# Verify tables were created in PostgreSQL9psql -U n8n_user -d n8n_db -c "\dt"1011# Expected tables include:12# workflow_entity13# credentials_entity14# execution_entity15# webhook_entity16# tag_entityExpected 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.
Migrate existing data from SQLite to PostgreSQL (optional)
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.
1# Step 1: Export workflows from SQLite (before changing DB_TYPE)2n8n export:workflow --all --output=./workflows-backup.json34# Step 2: Export credentials5n8n export:credentials --all --output=./credentials-backup.json67# Step 3: Switch to PostgreSQL (set the DB_TYPE and connection vars)8export DB_TYPE=postgresdb9export DB_POSTGRESDB_HOST=localhost10export DB_POSTGRESDB_PORT=543211export DB_POSTGRESDB_DATABASE=n8n_db12export DB_POSTGRESDB_USER=n8n_user13export DB_POSTGRESDB_PASSWORD=your_secure_password_here1415# Step 4: Start n8n to create the PostgreSQL schema16n8n start &17sleep 101819# Step 5: Import workflows into PostgreSQL20n8n import:workflow --input=./workflows-backup.json2122# Step 6: Import credentials23n8n import:credentials --input=./credentials-backup.jsonExpected result: All workflows and credentials from your SQLite installation are now available in the PostgreSQL-backed n8n instance.
Complete working example
1version: '3.8'23services:4 n8n:5 image: docker.n8n.io/n8nio/n8n6 container_name: n8n7 restart: unless-stopped8 ports:9 - '5678:5678'10 environment:11 # Database configuration12 - DB_TYPE=postgresdb13 - DB_POSTGRESDB_HOST=postgres14 - DB_POSTGRESDB_PORT=543215 - DB_POSTGRESDB_DATABASE=n8n_db16 - DB_POSTGRESDB_USER=n8n_user17 - DB_POSTGRESDB_PASSWORD=${N8N_DB_PASSWORD}18 - DB_POSTGRESDB_SCHEMA=public19 # n8n configuration20 - N8N_HOST=localhost21 - N8N_PORT=567822 - N8N_PROTOCOL=http23 - WEBHOOK_URL=http://localhost:5678/24 # Execution data retention (days)25 - EXECUTIONS_DATA_MAX_AGE=16826 - EXECUTIONS_DATA_PRUNE=true27 volumes:28 - n8n_data:/home/node/.n8n29 depends_on:30 postgres:31 condition: service_healthy3233 postgres:34 image: postgres:16-alpine35 container_name: n8n-postgres36 restart: unless-stopped37 environment:38 - POSTGRES_DB=n8n_db39 - POSTGRES_USER=n8n_user40 - POSTGRES_PASSWORD=${N8N_DB_PASSWORD}41 volumes:42 - postgres_data:/var/lib/postgresql/data43 healthcheck:44 test: ['CMD-SHELL', 'pg_isready -U n8n_user -d n8n_db']45 interval: 10s46 timeout: 5s47 retries: 54849volumes: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.
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?
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.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation