
You run n8n with Docker Compose on a VPS and a new version is out. Or you already ran docker compose pull, and since then a workflow fails. The update itself takes two commands, but a new version can change the database on its first start, and putting the old image tag back doesn't undo that. This guide pins the version, takes a backup a rollback can use, watches the migrations, and shows the rollback that works, on Ubuntu 24.04 and Debian 12.
Quick answer: Run a fixed version tag, not latest. On 30 October 2026, latest points at the stable release 2.45.7 and moves whenever n8n marks a newer one stable, while n8n 3.0, a major release with breaking changes, is already out as early access. To update, read the notes for every version between yours and the target, put the new number in .env, pull, stop the stack, archive every volume (the .n8n volume holds the encryption key), then start it and watch the migrations until /healthz/readiness returns 200. To roll back, restore the archives and the old version number together. The old tag alone is no rollback, because n8n only migrates its database forward.
Step 1: Pin the Version You Run Now
n8n's Docker page calls latest the stable version and next the unstable one, and says n8n "releases a new minor version most weeks". On Docker Hub on 30 October 2026, latest and stable were the same image as 2.45.7, and beta and next the same as 2.46.3. Versions 3.0.0 (27 October) and 3.0.1 (28 October) are there too: n8n calls 3.0.0 "an early access release", and its GitHub release is marked as a pre-release. With latest, the day you pull decides your version.
Docker commands need root, so they run with sudo here; on a Space-Node VPS for n8n and AI agents you have full root access. First find the version that runs now:
cd ~/n8n # the folder with your compose file
sudo docker compose exec n8n n8n --version
n8n is the service name in n8n's examples; use yours. Then turn the tag into a variable, as n8n's Postgres example does. Keep the image name you have and change only the part after the colon:
services:
n8n:
image: docker.n8n.io/n8nio/n8n:${N8N_VERSION}
Add the number from --version to the .env file next to your compose file, for example N8N_VERSION=2.45.5. Compose reads that file for interpolation. External task runners take the same variable on their n8nio/runners image, because n8n's task runner docs say its version "must match" the n8n image. Queue mode workers run the n8n image itself, so they use the same variable too.
sudo docker compose config --images
sudo docker compose up -d
The first command prints each image with its tag filled in: the n8n lines must show your number. If the image line changed, up -d recreates the container, still on the same version.
Pin PostgreSQL to a major version as well, such as postgres:16, and never change it in the same step. The README of that example explains that Postgres 18 can't read a data directory written by 16, so changing the tag alone stops with FATAL: database files are incompatible with server.
Step 2: Read Every Version Between Yours and the Target
n8n's update page gives three tips: update at least once a month, check the release notes for breaking changes, and try the update on a test instance first. Read every version you skip, not only the newest:
- Release notes: the feature-level changes per release. The 3.0 entry opens with a breaking changes warning.
- GitHub releases: every patch version with its fixes. The
.envin n8n's own compose setup says to take the latest stable number from there. - BREAKING-CHANGES.md: "all the versions which include breaking changes and how to upgrade". It lists minor releases too, such as 1.113.0 and 1.122.0, so a minor update can need action.
- A major version has its own page: 2.0 breaking changes if you are still on 1.x, and for 3.0 the 3.0 breaking changes plus the Migration Report under Settings > Migration Report, which lists the workflows and instance settings that need attention.
Then check the disk, because the new images and the backup both need room:
df -h
sudo docker system df -v
Under "Local Volumes space usage", the SIZE column shows what each volume holds. The backup needs about that much space again.
Step 3: Pull, Stop and Back Up Every Volume
n8n "recommends taking a full backup before updating" (backup and restore). For a rollback on the same server, the simplest full backup is a copy of every volume in the stack while all of it is stopped. n8n's docs say to stop n8n before copying SQLite, and PostgreSQL's manual says a file-level copy needs the server "shut down in order to get a usable backup". Restoring that copy puts the database, the encryption key and any binary data back exactly as they were.
First make the backup folder and list the stack's volumes:
cd ~/n8n
B=~/n8n-backup-$(date +%F)
mkdir -p -m 700 "$B" && cp .env docker-compose.yml "$B"/ # use your compose file's name
VOLS=$(sudo docker compose volumes -q)
echo "$VOLS" # your n8n volume, plus Postgres if you use it
docker compose volumes lists the volumes Compose created for this project. It arrived in Compose 2.38.0, and docker compose version shows yours. A volume Compose didn't create is missing from the list: one marked external: true, or one restored with docker run as in our n8n backup guide. If your n8n volume is missing, or your Compose is older, set the names by hand from sudo docker volume ls, for example VOLS="n8n_db_storage n8n_n8n_storage". If docker volume ls shows none for this stack, your data is in folders (see below). Then set the target version, pull, stop and archive:
sed -i 's/^N8N_VERSION=.*/N8N_VERSION=2.45.7/' .env # the target version
sudo docker compose pull
sudo docker compose down
for V in $VOLS; do
sudo docker run --rm -v "$V":/v -v "$B":/backup ubuntu:24.04 \
tar --numeric-owner -cf "/backup/$V.tar" -C /v .
done
ls -lh "$B"
pull downloads the new images while the old version keeps running, so n8n is only down from down onwards. That command removes the containers and networks but keeps named volumes unless you add -v, so never add it. The loop follows Docker's volume backup method: a throwaway Ubuntu container packs each volume into a tar file, with numeric owners, so a restore gives every file back to the same user ID.
The .n8n archive and .env hold the encryption key and passwords, which is why the folder is readable only by you. If a line under volumes: in your compose file starts with a path such as ./n8n_data:, that data lives in a folder: copy it after down with sudo cp -a ./n8n_data "$B"/.
This backup sits on the same disk as n8n. For copies that survive losing the server, see our n8n backup guide and PostgreSQL backup guide. Backups are not included in the plan price of our VPS hosting, but you can arrange them through a support ticket.
Step 4: Start the New Version and Watch the Migrations
sudo docker compose up -d
sudo docker compose logs -f n8n
n8n runs any pending database migrations each time it starts (base command). Its migration code then logs Migrations in progress, please do NOT stop the process., followed by a Starting migration and a Finished migration line for each one. Don't stop or restart anything until they finish. When n8n is ready, it prints Editor is now accessible via: with the URL. Ctrl+C stops following the log; n8n keeps running.
sudo docker compose exec n8n n8n --version
curl -i http://127.0.0.1:5678/healthz/readiness
The first must print the new number. The second should return status 200, which n8n's monitoring docs give "if the DB is connected and migrated". It assumes port 5678 is published on the host, as in n8n's examples.
Then test what matters to you: run a workflow that uses a saved credential, send a test request to a production webhook, watch the execution list for failed runs over the next hours, and in queue mode read the worker logs too. Keep the backup folder and the old image until all scheduled workflows have run on the new version. docker compose down leaves images in place, but docker image prune -a removes every image no container uses, the old n8n version included.
Roll Back: Restore the Backup and the Old Version Together
Putting the old number back in .env is not enough, for three reasons from n8n's own docs and code:
- n8n "only migrates a database forward", and its 3.0 breaking changes describe a migrated database as one "an older n8n version can't read".
- Not every migration can be undone. n8n's
db:revertcommand undoes only the last migration, needs the newer version still installed (otherwise it tells you to "upgrade n8n again"), and cancels with "was irreversible" for a migration without an undo step. Recent migrations such asRemoveUnusedInstanceAiSettingsare written that way. - Data formats change. Once n8n writes data with encryption key rotation, which 3.0 turns on by default, "older n8n versions can't read it", and n8n calls a database backup "the only recovery path" (rotate encryption keys).
So restore the archives and the old .env in one go:
cd ~/n8n
sudo docker compose down
B=~/n8n-backup-2026-10-30 # your folder from Step 3
for T in "$B"/*.tar; do
V=$(basename "$T" .tar)
sudo docker run --rm -v "$V":/v -v "$B":/backup ubuntu:24.04 \
sh -c "find /v -mindepth 1 -delete && tar --numeric-owner -xf /backup/$V.tar -C /v"
done
cp "$B/.env" .env
sudo docker compose up -d
sudo docker compose exec n8n n8n --version
The find part empties each volume before the archive goes back in, so nothing the new version wrote stays behind. That matters: n8n 3.0 renames ~/.n8n/binaryData to ~/.n8n/storage on its first start, and when both exist it "stops with an error instead of guessing which one to use". For a folder, run sudo rm -rf ./n8n_data && sudo cp -a "$B"/n8n_data ./ instead.
The rollback returns n8n to the moment of the backup. Workflows you edited and credentials you added after the update are gone, so redo them. Executions that ran on the new version still happened: emails they sent stay sent. Stay on the old number and watch GitHub releases for a fix; n8n published 2.45.5, 2.45.6 and 2.45.7 on 28, 29 and 30 October.
If It Still Fails
There was an error running database migrations. n8n logs this with the cause and exits. Roll back, then wait for the next patch release before you try that version again.
FATAL: database files are incompatible with server. The Postgres image moved to a new major version. Nothing is deleted: put the old major tag back and run sudo docker compose up -d.
Credentials could not be decrypted. n8n started without your original .n8n volume, or with another key. Our n8n backup guide has the fix for that error.
Only Code nodes fail. With external task runners, compare the n8n and runners lines in sudo docker compose config --images: the versions must match.
FAQ
Should I update to n8n 3.0 now?
Not in production while it is early access: on 30 October 2026, stable still points at 2.45.7. When you move, run Settings > Migration Report first, read the 3.0 breaking changes and take the Step 3 backup. 3.0 only supports Docker installs, renames the binary data folder and turns on encryption key rotation by default, so once it has run, that backup is your way back to 2.x.
Can I skip versions, for example from 2.30 to 2.45? Yes. n8n runs every pending migration at startup, so one update covers the versions in between. The work is the reading: check the notes and BREAKING-CHANGES.md for each version you skip. n8n advises updating at least once a month so these jumps stay small.
Does docker compose restart load the new version?
No. Docker's restart reference says changes to your compose configuration "are not reflected" after a restart. docker compose up -d recreates containers whose configuration or image changed, "preserving mounted volumes".
I updated without a backup and n8n broke. Can I go back? Not safely. First back up the current state as in Step 3, so nothing gets worse. Then update forward to the patch release that fixes your problem. Starting the old version on the migrated database is what n8n's docs warn against.
How long should I keep the backup? At least until every scheduled and webhook workflow has run on the new version. Old version tags stay on Docker Hub, so you can pull an old image again later; a backup can't be made after the fact.
Sources
All opened on 30 October 2026:
- n8n docs: Update n8n, Docker installation, Docker Compose installation, Release notes, 2.x release notes, 3.0 breaking changes, 3.0 migration tool, 2.0 breaking changes, Rotate encryption keys, Back up and restore, Monitor n8n, Use the command line, Set up task runners, Queue mode, Log variables
- n8n on GitHub: releases, n8n@3.0.0, BREAKING-CHANGES.md, db:revert, migration helpers, migration types, RemoveUnusedInstanceAiSettings migration, core constants, base command, start command, CLI launcher, get-n8n-compose.yml, n8n-hosting withPostgres and its README
- Docker Hub: n8nio/n8n tags
- Docker docs: docker compose up, down, pull, restart, volumes, config, logs, exec, docker run, docker image prune, docker system df, Volumes, Interpolation, Compose release 2.38.0
- PostgreSQL 18 docs: File System Level Backup
- Man pages: tar(1), find(1), cp(1), mkdir(1), sed(1), basename(1), date(1), df(1), ls(1), curl