Contents

n8n Backup and Update Tutorial: Restore Data and Upgrade Safely

What to back up

ItemLocationImportance
Database (workflows, credentials, execution history)PostgreSQL, or the SQLite file in n8n_dataRequired
Encryption keyN8N_ENCRYPTION_KEY, or the config file in n8n_dataRequired; without it, credentials cannot be decrypted
n8n_data data directoryDocker volumeRecommended
compose.yaml, .envDeployment folder on the hostRecommended

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

  1. Back up the database and .env (including N8N_ENCRYPTION_KEY) on the old host.
  2. On the new host, start PostgreSQL with the same compose.yaml and .env.
  3. Restore the database.
  4. Start n8n and confirm that your workflows and credentials work as expected.
  5. Update DNS to point to the new host.

Update n8n

n8n releases a new version about every week. Recommended steps:

  1. Read the release notes, especially for any breaking changes.

  2. Back up your data.

  3. Change the image version in compose.yaml, for example, n8nio/n8n:2.42.7 → the new version.

  4. Update:

    docker compose pull n8n
    docker compose up -d n8n
    docker compose logs -f n8n
  5. 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:

TagDescription
stableCurrent stable release (replaces the old latest)
betaTest 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