How to Migrate to n8n 3.0 Without Breaking Production (2026)
n8n 3.0 is a one-way upgrade. It removes 7 node types, cuts Code node timeout from 5 minutes to 60 seconds, and requires Docker. Run the Migration Report on 2.x first, test every revenue workflow in staging, and keep a restorable backup before touching production.
n8n 3.0 Is a One-Way Door
An n8n 3.0 migration moves you from n8n 2.x to a breaking major release. Once the database reaches 3.x, you can't safely reopen it with 2.x.
Rollback means restoring the old database, files, encryption key, and 2.x container.
That keeps a failed upgrade from becoming an outage.
Step 1: Inventory Everything That Can Break
Start on the latest n8n 2.x release. The Migration Report requires version 2.39 or newer.
Open Settings → Migration Report. Export the CSV before changing anything.
The report finds affected workflows and instance settings. It can also fix some issues by creating new workflow versions.
Don't trust the green checkmark alone.
The official n8n 3.0 announcement lists several removed nodes:
- Function
- Function Item
- Item Lists
- Cron
- Interval
- Legacy OpenAI
- Older AI Agent modes
Function becomes Code. Cron and Interval become Schedule Trigger.
Item Lists may need Split Out, Aggregate, Sort, Limit, Remove Duplicates, or Summarize. The replacement depends on what the workflow does.
Create a migration sheet with these columns:
| Field | What to record |
|---|---|
| Workflow | Exact workflow name and ID |
| Owner | Person responsible for approval |
| Revenue impact | Leads, content, support, reporting, or internal |
| Trigger | Schedule, webhook, form, API, or manual |
| Removed nodes | Every node flagged by the report |
| Credentials | HubSpot, Slack, OpenAI, Google, SMTP, and others |
| Binary data | Files, images, PDFs, audio, or attachments |
| Expected output | Record count, file, message, or status |
| Last successful run | Timestamp and execution ID |
| Test status | Not tested, passed, failed, or waived |
| Rollback owner | Person allowed to restore 2.x |
Tag each workflow as critical, important, or retired.
Critical means money stops when it fails. Lead capture, routing, booked-meeting alerts, email sends, and content publishing belong here.
Keep retired workflows off. "Won't fix" doesn't mean you should leave an old webhook exposed.
Expected outcome: Every active workflow has an owner, risk level, expected output, and test plan.
Step 2: Take a Backup You Can Actually Restore
A backup isn't real until you restore it somewhere else.
You need four things:
1. The n8n database 2. The full n8n data directory 3. The encryption key 4. Your Docker Compose file and environment settings
Credentials can carry into 3.x. They still depend on the same encryption key.
Lose that key and encrypted credentials become useless.
Set a backup folder first:
```bash export N8N_CONTAINER=n8n export BACKUP_DIR="$PWD/n8n-backup-$(date +%Y%m%d-%H%M%S)"
mkdir -p "$BACKUP_DIR" chmod 700 "$BACKUP_DIR" ```
Export workflows and credentials:
```bash docker exec "$N8N_CONTAINER" sh -lc ' rm -rf /tmp/n8n-export && mkdir -p /tmp/n8n-export/workflows /tmp/n8n-export/credentials && n8n export:workflow --backup --output=/tmp/n8n-export/workflows && n8n export:credentials --backup --output=/tmp/n8n-export/credentials '
docker cp "$N8N_CONTAINER":/tmp/n8n-export/. "$BACKUP_DIR/export" ```
Those credential exports still depend on your encryption setup. Store them like production secrets.
For SQLite, stop n8n before copying its data volume:
```bash docker stop "$N8N_CONTAINER"
docker run --rm \ --volumes-from "$N8N_CONTAINER" \ -v "$BACKUP_DIR":/backup \ alpine \ sh -lc 'tar czf /backup/n8n-data.tgz /home/node/.n8n'
docker start "$N8N_CONTAINER" ```
For PostgreSQL, take a database dump:
```bash export POSTGRES_CONTAINER=postgres export POSTGRES_USER=n8n export POSTGRES_DB=n8n
docker exec "$POSTGRES_CONTAINER" \ pg_dump -U "$POSTGRES_USER" -d "$POSTGRES_DB" -Fc \ > "$BACKUP_DIR/n8n-postgres.dump" ```
Save your configuration without printing secrets:
```bash install -m 600 .env "$BACKUP_DIR/compose.env" cp docker-compose.yml "$BACKUP_DIR/docker-compose.yml" docker inspect "$N8N_CONTAINER" > "$BACKUP_DIR/container-inspect.json" ```
Create checksums:
```bash find "$BACKUP_DIR" -type f -print0 \ | sort -z \ | xargs -0 sha256sum \ > "$BACKUP_DIR/SHA256SUMS" ```
Copy the backup off the n8n host. A disk failure shouldn't erase production and its backup together.
Expected outcome: You can build a fresh 2.x instance from the saved database, data directory, configuration, and encryption key.
Step 3: Build Staging in Docker
n8n 3.0 self-hosting requires Docker. npm and `npx n8n` installs aren't supported for the upgrade path.
Kubernetes and Helm setups aren't affected by that Docker change.
Use a separate host and database for staging. Give it its own volume, URL, and copy of the encryption key. Never point staging at the production database.
Pin an exact n8n image tag. Don't use `latest`.
Your staging Compose file should use a dedicated volume:
```yaml services: n8n: image: n8nio/n8n:${N8N_VERSION} restart: unless-stopped ports: - "5678:5678" env_file: - .env volumes: - n8n_staging_data:/home/node/.n8n
volumes: n8n_staging_data: ```
Start staging on the same 2.x version as production:
```bash export N8N_VERSION="YOUR_CURRENT_2X_VERSION" docker compose up -d ```
Restore the backup. Confirm that workflows, credentials, and recent execution data appear.
Then change only the image tag to the exact 3.x beta or stable version you're testing:
```bash export N8N_VERSION="YOUR_PINNED_3X_VERSION" docker compose pull docker compose up -d docker compose logs -f n8n ```
Block real outbound actions during testing.
Replace production credentials with test credentials. Route Slack messages to a test channel and email to a controlled inbox.
Add a dry-run switch before destructive nodes:
```text DRY_RUN=true ```
Use an IF node before CRM writes, email sends, ad changes, and publishing steps. The false path can log the intended action without sending it.
This simple flag makes test mode clear.
Expected outcome: Staging runs 3.x without touching production systems or sending real customer messages.
Step 4: Test Storage, Schedules, and Code Nodes
n8n 3.0 removes in-memory binary data mode. Binary files must use filesystem or supported external storage.
That affects workflows handling PDFs, images, CSV files, recordings, and email attachments.
If you use filesystem storage, `/home/node/.n8n` must sit on persistent storage. A container rebuild can't erase your files.
Test binary workflows with real file types and safe test data:
- Download a PDF
- Process an image
- Read a CSV
- Send an attachment
- Restart the container
- Retrieve the same file again
Queue mode needs extra care. Workers must access the same supported binary store.
Schedules also change.
Cron and Interval nodes move to Schedule Trigger. n8n says the new trigger uses its more durable scheduler.
The scheduler may retry jobs, so design for duplicates.
Every scheduled revenue workflow needs an idempotency key. Use something like:
```text workflow_id + scheduled_date + customer_id ```
Store that key before sending or writing. Reject duplicates on retries.
Add an external heartbeat for critical schedules. Better Uptime, UptimeRobot, or a separate cron host can check the last successful execution.
Your alert should fire when:
```text current_time - last_success > expected_interval + grace_period ```
Code nodes get another trap. The default timeout drops from five minutes to one minute.
Search for Code nodes that process large arrays, scrape pages, resize files, or call slow APIs. Split the work into batches or raise the configured timeout with a clear reason.
Turn on Retry on Fail for unstable API calls. Cap retries and delay them to avoid duplicate sends.
Expected outcome: Files survive restarts, schedules produce one intended result, and Code nodes finish within known limits.
Step 5: Cut Over With Guardrails
Run a final smoke test before production.
A workflow passing in the editor isn't enough. Test the full path from trigger to destination.
Use a small test flow for each trigger type:
1. Trigger with a unique test ID 2. Write the ID to a test table 3. Send one test notification 4. Record start time and finish time 5. Fail if any expected field is missing
Check these revenue paths:
- Web form to CRM
- New lead to owner assignment
- Qualified lead to booking link
- Content brief to draft
- Draft to approval
- Approval to publishing
- Failed workflow to Slack or email alert
Security defaults also changed.
Unverified community packages are off by default. Slack credentials require a signing secret. SSRF protection uses a larger block list when enabled.
The Slack change addresses a real risk. An n8n GitHub advisory described token theft through unverifiable Slack Trigger requests. The issue scored 6.3 out of 10.
GitGuardian found 321 reachable n8n instances accepting leaked API tokens. The tokens came from 4,576 public GitHub commits.
Rotate exposed tokens. Remove hard-coded secrets from HTTP Request nodes.
Schedule the cutover during a low-volume window. Pause incoming jobs where possible.
Keep the old 2.x setup intact and disconnected. Don't reuse its database after 3.x changes it.
If production fails, stop 3.x. Restore the pre-upgrade backup into a fresh 2.x instance.
Never point 2.x at a database already opened by 3.x.
Expected outcome: Production passes every smoke test, alerts work, and rollback remains possible through full restoration.
FAQ
How do I upgrade n8n without losing workflows and credentials?
Update to the latest 2.x release and run Settings → Migration Report. Back up the database, full data directory, encryption key, workflows, credentials, Compose file, and environment settings before starting 3.x.
How do I migrate n8n desktop or npm workflows to Docker?
Create a Docker instance on the same 2.x version first. Move the full n8n data directory into the Docker volume, preserve the encryption key, and confirm credentials before testing 3.x.
Can I downgrade from n8n 3.0 to 2.x?
No in-place downgrade is supported. Recovery requires stopping 3.x and restoring the complete pre-upgrade backup into a clean 2.x instance.
What should I test during an n8n Docker migration?
Test credentials, webhooks, schedules, binary files, Code nodes, community packages, Slack triggers, retries, and alerts. Every critical workflow should produce a known output from a controlled input.
How do I stop n8n workflows from silently failing?
Add failure workflows, external heartbeat checks, and alerts for missed success windows. For scheduled jobs, use idempotency keys so retries don't create duplicate leads, emails, or CRM records.
Related Reading
Can I roll back from n8n 3.0 to 2.x if something breaks?
No in-place downgrade exists. Recovery requires stopping 3.x and restoring a complete pre-upgrade backup into a clean 2.x instance. Never point a 2.x container at a database already opened by 3.0.
What is the Code node timeout in n8n 3.0?
The default Code node timeout drops from 5 minutes to 1 minute in n8n 3.0. Workflows that process large arrays, scrape pages, or call slow APIs must be split into batches or given an explicitly raised timeout before upgrading.
Which nodes were removed in n8n 3.0?
n8n 3.0 removes Function, Function Item, Item Lists, Cron, Interval, Legacy OpenAI, and older AI Agent modes. Function nodes become Code nodes. Cron and Interval nodes become Schedule Trigger.