Sheet & Flow
Launch offer: 20% off every product and bundle with code LAUNCH20 until October 14, 2026. Browse the store

How to Update Self-Hosted n8n in Docker Compose Without Losing Data (Tested 2.40 → 2.41)

Short on time? The n8n Production Self-Hosting Kit ($29) is the finished, tested version of what this tutorial builds.

Updating n8n is one command. Updating it safely is five, and the extra four are what save you when a release changes something you depend on.

We ran this exact procedure on September 30, 2026: a Docker Compose install with Postgres 17, a workflow and an encrypted credential, upgraded from n8n 2.40.6 to 2.41.4, then rolled back two different ways. The results are at the end.

Before you start: are you on a pinned version?

Open your docker-compose.yml. If the image line ends in :latest (or has no tag at all), you are not really choosing when you upgrade: any docker compose pull, server rebuild or a colleague's "quick fix" can jump you several versions at once.

Pin it through .env instead:

# docker-compose.yml
    image: docker.n8n.io/n8nio/n8n:${N8N_VERSION}

# .env
N8N_VERSION=2.40.6

Now an upgrade is a one-line, reviewable change. (Our self-hosting tutorial and the free Docker Compose generator both set it up this way.)

To see which version you're running right now:

docker compose exec n8n n8n --version

Step 1: Pick the target version and read the release notes

On the day we tested, the Docker tags were latest = stable = 2.41.4 and next = beta = 2.42.1. For a production instance, upgrade to the current stable release, not next/beta.

Skim the release notes for every version between yours and the target (the n8n docs publish them per version). Look for "breaking", removed nodes, and changed environment variable defaults. For big jumps, go one minor version at a time.

Step 2: Back up the database and the encryption key

From the folder with your docker-compose.yml:

docker compose exec -T postgres pg_dump -U n8n -d n8n -Fc > n8n-before-upgrade.dump
cp .env env-before-upgrade.backup

The .env copy matters as much as the dump, because it holds N8N_ENCRYPTION_KEY. A database restored with the wrong key opens fine but every credential fails with "Credentials could not be decrypted". Move both files off the server (or at least out of the Docker volume) before continuing. Our backup tutorial covers doing this on a schedule.

Our test dump was about 480 KB for a small instance. Yours will be larger if you keep a lot of execution history.

Step 3: Change the version and pull

Edit one line in .env:

N8N_VERSION=2.41.4

Then pull the new image before stopping anything, so the downtime is only the restart:

docker compose pull n8n
docker compose up -d n8n

up -d recreates only the n8n container. Postgres and your data volume are untouched. On start, n8n runs its database migrations automatically. In our drill it ran 5 migrations and was serving again about 40 seconds after pull began.

Step 4: Verify before you walk away

docker compose ps
docker compose exec n8n n8n --version
docker compose logs --tail 100 n8n

Check three things:

  1. n8n --version prints the new version (ours printed 2.41.4).
  2. The log has no errors after "Finished migration". Deprecation notices are normal: 2.41 warns about future default changes for things like N8N_RUNNERS_MODE and N8N_RUNNERS_TASK_TIMEOUT. Set the ones you rely on explicitly so a later release doesn't change them under you.
  3. Your credentials still decrypt. Open a workflow that uses a credential and run it once, or run the test from the backup tutorial. In our drill, the same workflow count and the same decrypted credential value came back after the upgrade.

Also open any workflow with a Webhook trigger and confirm the production URL still points at your domain, not localhost:5678.

Step 5: If something breaks, roll back properly

The tempting rollback is to put the old version back in .env and restart. Don't rely on it. n8n migrates the database forward on upgrade and does not migrate it back when you start an older version.

In our drill, the naive rollback (2.41.4 → 2.40.6 on the already-migrated database) did start and showed the workflow. That was a small minor-version jump with additive migrations; there is no guarantee the next one will be as forgiving, and an old version running on a newer schema can fail in ways that only show up later.

The rollback that is guaranteed to be consistent is restoring the pre-upgrade backup:

docker compose stop n8n
docker compose exec -T postgres psql -U n8n -d postgres -c 'DROP DATABASE n8n WITH (FORCE);' -c 'CREATE DATABASE n8n OWNER n8n;'
docker compose exec -T postgres pg_restore -U n8n -d n8n --no-owner < n8n-before-upgrade.dump
cp env-before-upgrade.backup .env
docker compose up -d n8n

Anything that happened between the upgrade and the rollback (new executions, edited workflows) is lost, which is another reason to verify right after upgrading rather than a week later. In our drill, the restored 2.40.6 instance came back with the workflow and a credential that decrypted correctly.

Drill results (September 30, 2026)

Step Result
Start on 2.40.6, create a workflow + an encrypted credential OK
Back up: pg_dump -Fc + .env copy 480 KB dump
Upgrade to 2.41.4 (pull + up -d) 5 migrations, ~40 s until ready
After upgrade: workflows / credential decrypts 1 / yes
Naive rollback to 2.40.6 on the migrated database Started (not recommended; see Step 5)
Proper rollback: restore dump + 2.40.6 Workflows 1, credential decrypts

Test setup: Docker Compose v2.39, postgres:17-alpine, docker.n8n.io/n8nio/n8n. (On our test machine both containers used host networking; the procedure is identical on the default Compose network.)

Common mistakes

  • Upgrading without a dump because "it's just a minor version". The dump takes seconds. Restoring from nothing takes days.
  • Backing up the database but not .env. Without the original N8N_ENCRYPTION_KEY, credentials are unrecoverable. The free n8n-key-check CLI confirms a key decrypts your credentials before you need it.
  • Using latest in production. You lose control over when upgrades happen and which versions you skip.
  • Upgrading on Friday evening. Upgrade when you have an hour to watch the logs and run your key workflows.

Done-for-you version

The n8n Production Self-Hosting Kit turns this into scripts: upgrade.sh <version> takes a backup first, refuses latest, pulls, restarts and waits for the health check (with an optional automatic rollback), and there's an encrypted backup.sh, a restore.sh that refuses a mismatched key, and a restore drill that proves your credentials decrypt. Tested with Docker Compose, Postgres 17 and Caddy for HTTPS.

Not affiliated with n8n GmbH.

Free tool: n8n Docker Compose Generator (Postgres + HTTPS)

Written with AI assistance. Every formula, command and number on this page was tested before publishing (see each section). Product links go to our store.