n8n Has No Version Control: Build a Backup and Rollback System

Mike Holownych
Last verified: July 28, 2026
#n8n#automation
Share:

Quick Answer

n8n has no version control for workflows — every save permanently overwrites the previous state, with no branches, no commit history, and no built-in rollback. Build your own by capturing a snapshot of the workflow’s JSON via n8n’s API before every meaningful change, storing it with a timestamp, and having a rollback workflow that can push a stored snapshot back through the same API on demand.

The Version Control Gap

n8n stores each workflow in your database as a single JSON object. When you click “Save,” the platform overwrites that record entirely. There’s no diff, no history of what changed between versions, and no way to see what the workflow looked like an hour ago short of restoring an entire database backup.

The execution history n8n does keep tracks runs, not configuration changes — you can see that an execution failed, but not what the workflow looked like before the edit that caused it to start failing. A full database dump can technically get you back to an earlier state, but it’s a blunt instrument: it rolls back everything in the database to that point in time, not just the one workflow you actually need reverted.

Traditional software development solved this decades ago with version control: every change is a commit, and reverting to a known-good state takes seconds. n8n workflows are business logic that changes just as often as application code, and they don’t get the same protection by default.

This isn’t a hypothetical edge case. Any workflow that’s actively maintained — new nodes added, credentials rotated, mappings adjusted as an upstream API changes — eventually gets an edit that breaks something. Without your own backup system, “roll back to what worked yesterday” isn’t an option n8n gives you; you’re reconstructing the previous configuration from memory, screenshots, or whatever you can piece together.

Build a Workflow Versioning System

This uses n8n’s own REST API and a webhook trigger to capture a snapshot of a workflow’s JSON before you touch it, and a companion workflow to push a stored snapshot back if the change breaks something.

Step 1: Create the Backup Workflow

A workflow triggered by webhook that fetches the current state of a target workflow and stores it:

{
  "nodes": [
    {
      "name": "Webhook Trigger",
      "type": "n8n-nodes-base.webhook",
      "parameters": {
        "path": "backup-workflow",
        "httpMethod": "POST"
      }
    },
    {
      "name": "Get Workflow Data",
      "type": "n8n-nodes-base.httpRequest",
      "parameters": {
        "url": "={{$parameter[\"n8n_base_url\"]}}/api/v1/workflows/{{$json[\"workflow_id\"]}}",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "n8nApi"
      }
    },
    {
      "name": "Create Backup Record",
      "type": "n8n-nodes-base.postgres",
      "parameters": {
        "operation": "insert",
        "table": "workflow_backups",
        "columns": "workflow_id, backup_data, created_at, version_tag",
        "additionalFields": {
          "workflow_id": "={{$json[\"id\"]}}",
          "backup_data": "={{JSON.stringify($json)}}",
          "created_at": "={{new Date().toISOString()}}",
          "version_tag": "={{$parameter[\"version_tag\"] || 'auto-backup'}}"
        }
      }
    }
  ]
}

Step 2: Database Schema for Version Storage

CREATE TABLE workflow_backups (
  id SERIAL PRIMARY KEY,
  workflow_id VARCHAR(50) NOT NULL,
  backup_data JSONB NOT NULL,
  created_at TIMESTAMP DEFAULT NOW(),
  version_tag VARCHAR(100),
  is_working BOOLEAN DEFAULT true
);

CREATE INDEX idx_workflow_backups_id_date ON workflow_backups(workflow_id, created_at DESC);

Step 3: Trigger a Backup Before Every Change

Call the backup webhook from wherever your change process starts — a deploy script, a pre-edit checklist, or manually before opening the editor:

// Run before editing any workflow you'd need to recover
const backupUrl = 'https://your-n8n-instance.com/webhook/backup-workflow';
const workflowId = $json.id;

await fetch(backupUrl, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    workflow_id: workflowId,
    version_tag: `pre-update-${new Date().toISOString()}`
  })
});

Step 4: Build the Rollback Workflow

The restoration side: look up a stored snapshot by workflow ID and version tag, then push it back through the API.

{
  "nodes": [
    {
      "name": "Rollback Trigger",
      "type": "n8n-nodes-base.webhook",
      "parameters": {
        "path": "rollback-workflow",
        "httpMethod": "POST"
      }
    },
    {
      "name": "Get Backup Version",
      "type": "n8n-nodes-base.postgres",
      "parameters": {
        "operation": "select",
        "table": "workflow_backups",
        "where": {
          "workflow_id": "={{$json[\"workflow_id\"]}}",
          "version_tag": "={{$json[\"version_tag\"]}}"
        }
      }
    },
    {
      "name": "Restore Workflow",
      "type": "n8n-nodes-base.httpRequest",
      "parameters": {
        "url": "={{$parameter[\"n8n_base_url\"]}}/api/v1/workflows/{{$json[\"workflow_id\"]}}",
        "method": "PUT",
        "body": "={{JSON.parse($json[\"backup_data\"])}}",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "n8nApi"
      }
    }
  ]
}

Trigger a rollback the same way you triggered the backup — a webhook call with the workflow_id and the version_tag you want to restore:

curl -X POST https://your-n8n-instance.com/webhook/rollback-workflow \
  -H "Content-Type: application/json" \
  -d '{"workflow_id": "123", "version_tag": "pre-update-2026-07-28T14:00:00.000Z"}'

What This Doesn’t Solve

This is a manual-trigger backup system, not real version control. It only protects you if you actually call the backup webhook before making a change — it won’t catch edits made without going through that step. It also doesn’t diff versions for you; you’re restoring a full prior state, not merging changes. For workflows where that matters, treat this as a floor, not a complete solution: pair it with a habit (or a hook) that makes the pre-change backup automatic rather than something you have to remember.

See Automation Governance for the broader discipline this fits into — ownership, change control, and promotion for production automation generally, not just the backup mechanics covered here.

MH

About Mike Holownych

Building AI Syndicate—governance infrastructure for AI agents in regulated environments. 20+ years enterprise operations, now applying that reliability discipline to AI deployment.