If you run n8n in production, upgrading from 1.x to 2.0 is bigger than a version bump.
The n8n 2.0 changes several defaults around Code nodes, task runners, Python execution, file access, databases, OAuth, binary data, and workflow publishing.
Some of these changes are also security improvements while the others can actually change how an existing workflow behaves.
But, instead of listing every new feature in n8n 2.0, this article focuses on the real questions that matter when you are running real workflows:
- What actually changed?
- Which workflows are most likely to break?
- What should you check before upgrading?
- How do you test the migration?
- When does upgrading make sense?
The First Thing to Understand: 2.0 Changes Defaults
The biggest theme in n8n 2.0 is being secure natively.
Task runners are enabled by default, Code node access to environment variables is blocked by default, and nodes capable of arbitrary command execution are disabled by default.
That means a workflow that performed on previous versions of n8n like 1.x can behave differently after the upgrade even if you never changed the workflow itself.
For developers, this is more important than the UI changes.
The migration question is not:
"Does my workflow open, function?"
It is:
"Does my workflow still execute with the same inputs, permissions, side effects, and outputs?"
1. Task Runners Are Now the Default
This is one of the most important changes if your workflows use Code nodes.
In n8n 2.0, task runners are enabled by default and Code node executions run on task runners. The result is having stronger isolation and security.
Before upgrading, test your Code nodes with:
N8N_RUNNERS_ENABLED=true
This lets you find compatibility problems before making the 2.0 upgrade.
Why this matters
Imagine you have:
const secret = process.env.MY_API_KEY;
return [{
json: {
key: secret
}
}];
In n8n 2.0, environment-variable access from the Code node is blocked by default.
The relevant setting is:
N8N_BLOCK_ENV_ACCESS_IN_NODE=true
If your workflow depends on environment variables inside the Code nodes, it can stop working after the upgrade.
Better approach
Don't use the Code node as a secret store.
Use n8n credentials for secrets whenever possible.
For example:
Bad pattern:
Code Node
↓
process.env.API_KEY
↓
HTTP Request
Prefer:
Credential
↓
HTTP Request
Applying this change also makes the workflow easier to maintain.
2. $evaluateExpression() in Code Nodes Can Break
This is a particularly easy migration issue to miss.
n8n 2.0's secure task-runner model means:
$evaluateExpression()
no longer works inside the Code node as it did before. n8n documents this as a breaking change.
For example, if you have:
const result = $evaluateExpression(
"{{$json.customer.name}}"
);
you should not depend on utilizing that pattern after upgrading.
What can you do?
Move the expression evaluation outside the Code node.
For example:
Edit Fields
↓
evaluate expression
↓
Code Node
↓
business logic
Or write the JavaScript logic directly.
n8n also documents an insecure-mode workaround, but it is intended as a temporary compatibility option rather than the preferred production solution.
3. Python Code Nodes Are Changing
If you use Python inside n8n, this deserves special focus and attention.
n8n 2.0 removes the previous Pyodide-based Python Code implementation and moves Python execution to the task-runner model.
Python Code nodes require task runners in external mode.
There is also a compatibility difference, namely the native Python implementation doesn't support the same built-in variables that were available in the previous Pyodide-based implementation.
For example, code relying on:
_input
will need to be reviewed once again.
So, Before upgrading
Search your workflows for:
Python
Code
AI Agent + Python tools
Then, test each one separately.
Don't automatically assume:
"The node is still called Python, so my existing code will behave the same."
The execution environment has changed, so must your code.
4. ExecuteCommand and LocalFileTrigger Are Disabled by Default
This is another security-related change.
n8n 2.0 disables these nodes by default:
- ExecuteCommand
- LocalFileTrigger
They can execute commands or interact with the filesystem, which is why n8n tightened their default availability.
If your workflow contains:
Webhook
↓
ExecuteCommand
↓
Process file
↓
Upload result
don't assume the workflow will behave exactly the same after upgrading.
You need to review the node usage and decide which particular ones are actually required and functioning.
If it is required, n8n provides configuration through NODES_EXCLUDE, but enabling powerful nodes should be an intentional infrastructure decision. It is not something you blindly copy from your old configuration.
5. File Access Is More Restricted
Workflows that read and write local files also need attention.
n8n 2.0 introduces a default restriction around file access.
For example:
Read Binary Files
↓
Process
↓
Write Binary File
may need its file paths reviewed.
The default allowed location is:
~/.n8n-files
for the relevant file operations.
This matters particularly for self-hosted installations processing the following types of files:
- PDFs
- Images
- CSV files
- Documents
- Generated reports
- Uploaded files
Thus, before upgrading, identify every workflow using file-system nodes.
6. MySQL and MariaDB Are No Longer Supported as n8n Storage Backends
This is a major infrastructure change.
n8n 2.0 drops MySQL and MariaDB as storage backends for n8n itself. The n8n 2.0 recommends PostgreSQL for long-term compatibility.
Important distinction to note:
The MySQL node is still supported even if it's not the default recommendation.
The change is about the database used by n8n to store its own data.
So these are different:
n8n internal database
≠
MySQL node connecting to your application database
If your n8n installation itself uses MySQL or MariaDB, migration needs to happen before the upgrade.
If your workflow simply connects to a MySQL database using the MySQL node, that's a different situation.
7. SQLite Gets a New Driver
SQLite users also need to know about the database driver change.
n8n removes the legacy SQLite driver and uses the pooled driver instead.
The new driver uses:
- WAL mode
- One write connection
- A pool of read connections
n8n says its benchmarks showed the pooled implementation can be up to 10× faster than previous offering, however, the actual performance may vary depending on the workload.
You can test the pooled behavior before upgrading by setting:
DB_SQLITE_POOL_SIZE=2
The important part isn't chasing the benchmark number.
It's testing your actual workload.
8. Binary Data Is No Longer Stored In Memory by Default
This is especially relevant if your workflows process files.
Older configurations could use:
default
for in-memory binary data.
n8n 2.0 removes that mode.
The supported approaches are:
filesystem
database
S3
depending on your configuration.
Think about a workflow like:
Webhook
↓
PDF Upload
↓
AI Processing
↓
Extract Data
↓
Store Document
If you process large files, your storage configuration now matters more.
Before upgrading, check:
- How much binary data do we process?
- Where is it stored?
- How much disk space is available?
- Are old files being cleaned up?
- Are workers sharing the same storage?
A version upgrade can expose storage assumptions that were previously hidden.
9. OAuth Callback Authentication Changes
n8n 2.0 changes the default behavior for OAuth callback URLs.
Authentication is required by default.
The relevant configuration changes from the previous permissive behavior to:
N8N_SKIP_AUTH_ON_OAUTH_CALLBACK=false
n8n recommends testing OAuth integrations before upgrading.
If you have workflows using:
- Google OAuth
- Microsoft OAuth
- Slack OAuth
- Custom OAuth providers
- Other OAuth-based integrations
test the authentication flow instead of only testing the workflow execution.
A workflow can look healthy despite its authorization flow being broken, correct it.
10. Subworkflow Output Behavior Matters
This is one of the changes that quietly affect workflow logic.
In n8n 2.0, a parent workflow receives the result of the child subworkflow execution.
This also fixes behavior around subworkflows containing Wait nodes.
Consider:
Parent Workflow
↓
Execute Sub-workflow
↓
Wait
↓
Return result
This becomes especially important when your n8n workflow automation is connected to CRMs, databases, APIs, or other business-critical systems.
If your parent workflow expects a particular output structure from the child workflow, test it explicitly.
Don't just check whether the subworkflow completes, also check the actual JSON reaching the next node.
For example:
console.log($json);
or inspect the execution data and compare it with your pre-upgrade output.
This is the kind of change that creates subtle bugs rather than an obvious startup failure.
11. Workflow Publishing Is More Deliberate
n8n 2.0 introduces a clearer separation between editing and putting changes live.
The model becomes:
Save
↓
Keep editing
↓
Publish
↓
Production receives the new version
Instead of treating Save as an immediate production update for activated workflows, n8n 2.0 introduces an explicit Publish action.
For teams working on production workflows, this is an important operational change.
It gives you a clearer distinction between:
"I changed the workflow"
and:
"I want this version running in production."
That distinction becomes increasingly important as workflows become business-critical.
12. CLI Commands Have Changed Too
If you manage n8n through automation or deployment scripts, don't only inspect the visual workflows.
The CLI also has changes that may be breaking things.
For example, the old:
update:workflow
command is being replaced by:
publish:workflow
and:
unpublish:workflow
The --all behavior is also being removed from the publishing path to reduce the risk of accidentally publishing workflows in production.
So, if your deployment pipeline contains n8n CLI commands, search those scripts before upgrading.
13. Don't Forget Docker
If you're self-hosting n8n with Docker and using external task runners, there is another important change.
The main:
n8nio/n8n
image no longer includes the task runner for external mode.
You need:
n8nio/runners
for external task runners.
A simplified setup becomes:
Docker
│
┌────────┴─────────┐
│ │
n8nio/n8n n8nio/runners
│ │
└────────┬─────────┘
↓
Task execution
If you're using Docker Compose, review your runner configuration before changing the n8n image.
The Most Useful Part: Use the Migration Report
Don't manually inspect hundreds of workflows if your instance can scan them for you.
n8n 2.0 includes a Migration Report.
Go to:
Settings → Migration Report
The tool checks both:
- Workflow Issues
- Instance Issues
The workflow section identifies affected workflows and nodes, and it also shows severity, affected workflow count, execution information, and the relevant documentation.
The instance issues section focuses on configuration changes affecting the whole n8n installation.
The recommended order
Don't fix everything randomly.
Use:
Critical
↓
Medium
↓
Low
Critical issues are the ones n8n identifies as capable of breaking workflows.
After making changes, refresh the report and verify that the compatibility count covers your workflows.
My n8n 2.0 Pre-Upgrade Checklist
Before touching production, I would run through this checklist.
Code
- [ ] Search Code nodes
- [ ] Test environment-variable access
- [ ] Search for
$evaluateExpression() - [ ] Test JavaScript execution
Python
- [ ] Find Python Code nodes
- [ ] Check task-runner configuration
- [ ] Review
_inputusage - [ ] Test Python tools
Files
- [ ] Find Read/Write File nodes
- [ ] Check allowed directories
- [ ] Check disk capacity
- [ ] Review binary-data configuration
Database
- [ ] Identify n8n's storage backend
- [ ] Check for MySQL/MariaDB
- [ ] Review SQLite configuration
- [ ] Backup the database
Integrations
- [ ] Test OAuth workflows
- [ ] Test webhooks
- [ ] Test external APIs
- [ ] Test subworkflows
Infrastructure
- [ ] Check task runners
- [ ] Check Docker configuration
- [ ] Check environment variables
- [ ] Check CLI/deployment scripts
Workflow behavior
- [ ] Test critical workflows
- [ ] Compare input/output JSON
- [ ] Test error paths
- [ ] Test retries
- [ ] Test file processing
- [ ] Test production side effects
How I Would Actually Upgrade a Production n8n Instance
I wouldn't start by changing production, I'd use a separate environment first.
n8n's own update guidance recommends using environments to create a test version and testing the update there first. It also recommends reviewing release notes and updating regularly rather than allowing large version gaps to accumulate.
A practical sequence is:
Production n8n
│
▼
Backup
│
▼
Clone / Test Environment
│
▼
Run Migration Report
│
▼
Fix Critical Issues
│
▼
Upgrade Test Instance
│
▼
Run Critical Workflows
│
▼
Compare Outputs
│
▼
Test OAuth / APIs / Files
│
▼
Upgrade Production
│
▼
Monitor Executions
The key step is output comparison.
A workflow that finishes successfully isn't necessarily correct by itself.
For critical workflows, compare:
- Input
- Output
- HTTP responses
- Database writes
- CRM updates
- Messages sent
- Files generated
before and after the upgrade.
So, Should You Upgrade to n8n 2.0?
There isn't one true answer for every deployment.
A better useful question is:
How much of your current n8n installation depends on the behaviors that changed?
If your workflows are mostly:
Webhook
→ HTTP Request
→ Transform
→ CRM
→ Database
your migration surface may be relatively small, making it ideal to upgrade.
If your instance heavily depends on:
- Code nodes
- Python
- Environment variables
- Local files
- ExecuteCommand
- MySQL/MariaDB as n8n storage
- Custom infrastructure
- OAuth
- Subworkflows
- CLI deployment
you have more to test and fix.
That doesn't mean you shouldn't upgrade.
It means you should treat the upgrade as an infrastructure migration, not a button click ordeal.
The Bigger Change in n8n 2.0
The interesting part of n8n 2.0 isn't a flashy new node.
It's the direction of the platform.
n8n is tightening security defaults, isolating Code execution with task runners, removing legacy infrastructure, improving workflow publishing, and making production behavior more deliberate.
n8n describes the major themes of the upgrade as security, reliability, and performance.
For developers, that means an important shift:
Your n8n workflow is becoming more like production software.
That means you should treat it accordingly:
Version control
+
Testing
+
Environment separation
+
Secrets management
+
Monitoring
+
Backups
+
Controlled deployment
The more critical the workflow becomes, the less you should rely on the simplistic approach of:
"It worked when I clicked Execute."
Final Takeaway
n8n 2.0 is not simply a cosmetic upgrade.
The changes that deserve the most attention are:
- Task runners enabled by default
- Code node environment access restricted
- $evaluateExpression() removed from Code nodes
- Python execution moved to task runners
- ExecuteCommand and LocalFileTrigger disabled by default
- File access becomes more restricted
- MySQL/MariaDB removed as n8n storage backends
- Binary data storage behavior changes
- OAuth callback authentication becomes stricter
- Workflow publishing becomes more explicit
The good news is that you don't have to guess whether your instance is affected.
Run the Migration Report, fix the critical issues, and test in a non-production environment. Then, compare workflow outputs, and only then upgrade in production.
For a production n8n installation, this is a much safer upgrade strategy than simply changing:
n8n:1.x
to:
n8n:2.x
and hoping everything keeps working.
Top comments (0)