Contents
n8n Backup and Update Tutorial: Restore Data and Upgrade Safely
What to back up
| Item | Location | Importance |
|---|---|---|
| Database (workflows, credentials, execution history) | PostgreSQL, or the SQLite file in n8n_data | Required |
| Encryption key | N8N_ENCRYPTION_KEY, or the config file in n8n_data | Required; without it, credentials cannot be decrypted |
n8n_data data directory | Docker volume | Recommended |
| compose.yaml, .env | Deployment folder on the host | Recommended |
Method 1: Export workflows with the CLI
n8n includes export commands that let you export workflows as JSON files (which are suitable for version control in Git):
docker compose exec n8n n8n export:workflow --all --separate --output=/home/node/.n8n/backup/workflows/
docker compose exec n8n n8n export:credentials --all --separate --output=/home/node/.n8n/backup/credentials/
--separate: one file per workflow- Exported credentials remain encrypted by default; you must use the same encryption key to use them
Copy the files out of the container:
docker compose cp n8n:/home/node/.n8n/backup ./n8n-backup-$(date +%F)
To restore:
docker compose exec n8n n8n import:workflow --separate --input=/home/node/.n8n/backup/workflows/
docker compose exec n8n n8n import:credentials --separate --input=/home/node/.n8n/backup/credentials/
Method 2: Back up the database
PostgreSQL
docker compose exec -T postgres pg_dump -U n8n n8n | gzip > n8n-db-$(date +%F).sql.gz
To restore (to a fresh database):
gunzip -c n8n-db-2026-10-12.sql.gz | docker compose exec -T postgres psql -U n8n -d n8n
SQLite
The SQLite database (database.sqlite) is in the n8n_data volume. Stop n8n before backing it up to avoid copying a file while it is being written:
docker compose stop n8n
docker run --rm -v n8n_n8n_data:/data -v "$PWD":/backup alpine \
tar czf /backup/n8n-data-$(date +%F).tar.gz -C /data .
docker compose start n8n
(The volume name is "project-name_n8n_data"; you can verify it with docker volume ls.)
Automate backups
Use cron to create a daily backup, then sync the backup file somewhere else (another host or cloud storage):
# /etc/cron.daily/n8n-backup
#!/bin/sh
cd /opt/n8n
docker compose exec -T postgres pg_dump -U n8n n8n | gzip > /backup/n8n-$(date +%F).sql.gz
find /backup -name 'n8n-*.sql.gz' -mtime +30 -delete
Test restoring from your backups regularly to make sure they work.
Move to a new host
- Back up the database and
.env(includingN8N_ENCRYPTION_KEY) on the old host. - On the new host, start PostgreSQL with the same compose.yaml and
.env. - Restore the database.
- Start n8n and confirm that your workflows and credentials work as expected.
- Update DNS to point to the new host.
Update n8n
n8n releases a new version about every week. Recommended steps:
-
Read the release notes, especially for any breaking changes.
-
Back up your data.
-
Change the image version in compose.yaml, for example,
n8nio/n8n:2.42.7→ the new version. -
Update:
docker compose pull n8n docker compose up -d n8n docker compose logs -f n8n -
Confirm that your important workflows work as expected.
n8n automatically runs database migrations on startup. You can see migration progress in the logs.
Version tags
n8n 2.x image tags:
| Tag | Description |
|---|---|
stable | Current stable release (replaces the old latest) |
beta | Test release that may be unstable (replaces the old next) |
2.42.7, etc. | Pinned version; recommended for production |
Upgrade from n8n 1.x to 2.x
Version 2.0 includes several breaking changes. Before upgrading, read the official 2.0 breaking changes guide. Key changes include:
- The Activate toggle is now Publish / Unpublish: saving does not take effect immediately; you need to publish.
- Task runners are enabled by default, and the Code node runs in a separate process.
- The Code node cannot read environment variables by default. Update any older workflows that use
$env. - The Python Code node now uses native Python and requires an external task runner. Its syntax differs from the previous version.
- Executing system commands (Execute Command) and local file triggers are disabled by default.
- File read/write nodes can access only specific folders by default.
- MySQL / MariaDB are no longer supported as n8n databases. Migrate to PostgreSQL or SQLite first.
- Data returned from a sub-workflow to its parent workflow is now the output of the sub-workflow's last node.
- The Start node has been removed. Use Manual Trigger instead.
We recommend trying 2.x with backed-up data in a test environment first. Upgrade your production environment after confirming that all important workflows work as expected.
Updated October 12, 2026