KEEP LEARNING
Build the bigger picture.
The Workflow Engineer connects individual n8n concepts to testing, deployment and running a complete workflow.
Tips > Ops & Security
Stopping n8n for an upgrade interrupts active executions and makes webhooks return errors.
A blue-green deployment upgrades n8n with no webhook downtime by running the new version alongside the old one on the same database. You start the green instance, wait for its health check to pass, switch the reverse proxy to it, then stop the blue instance. n8n's migration system applies schema changes when the new version starts.
Stopping n8n for an upgrade interrupts active executions and makes webhooks return errors. A blue-green deployment runs the new version alongside the old one, verifies it works, then switches traffic. Both versions share the same database, so n8n's migration system handles schema changes during startup of the new version.
Real-world example: You upgrade from 1.93.0 to 1.94.1 without any webhook downtime.
Both versions share one PostgreSQL database in a Docker Compose file:
services:
postgres:
image: postgres:16-alpine
restart: unless-stopped
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U n8n_user -d n8n_db"]
interval: 10s
timeout: 5s
retries: 5
n8n-blue:
image: n8nio/n8n:1.93.0
restart: unless-stopped
environment:
DB_TYPE: postgresdb
DB_POSTGRESDB_HOST: postgres
DB_POSTGRESDB_DATABASE: n8n_db
DB_POSTGRESDB_USER: n8n_user
DB_POSTGRESDB_PASSWORD: ${POSTGRES_PASSWORD}
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://localhost:5678/healthz || exit 1"]
interval: 30s
timeout: 10s
retries: 3
n8n-green:
image: n8nio/n8n:1.94.1
restart: unless-stopped
environment:
DB_TYPE: postgresdb
DB_POSTGRESDB_HOST: postgres
DB_POSTGRESDB_DATABASE: n8n_db
DB_POSTGRESDB_USER: n8n_user
DB_POSTGRESDB_PASSWORD: ${POSTGRES_PASSWORD}
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://localhost:5678/healthz || exit 1"]
interval: 30s
timeout: 10s
retries: 3
volumes:
postgres_data:#!/usr/bin/env bash
set -euo pipefail
# Step 1: Start the green (new) instance
docker compose -f docker-compose.blue-green.yml up -d n8n-green
# Step 2: Wait for green to pass health checks
echo "Waiting for green instance to become healthy..."
timeout 180 bash -c '
until docker inspect --format="{{.State.Health.Status}}" n8n-green-1 2>/dev/null | grep -q healthy; do
sleep 5
done
'
echo "Green instance is healthy."
# Step 3: Update Caddy to point to green
# (swap upstream in Caddyfile from n8n-blue:5678 to n8n-green:5678)
sed -i 's/n8n-blue:5678/n8n-green:5678/' Caddyfile
docker exec caddy-1 caddy reload --config /etc/caddy/Caddyfile
# Step 4: Verify traffic is flowing to green
sleep 10
curl -sf https://n8n.example.com/healthz > /dev/null && echo "Traffic switched to green."
# Step 5: Stop the blue (old) instance
docker compose -f docker-compose.blue-green.yml stop n8n-blue
echo "Blue-green deployment complete."Warning: Database Migrations. n8n runs database migrations on startup. Once the green instance starts and migrates the schema, the blue instance may not be compatible with the new schema. Keep the cutover window short and always have a database backup from before the migration.
This approach eliminates the 30-120 second downtime window that a simple docker compose pull && docker compose up -d creates.
Related: Set a Unique Encryption Key and Back It Up · Configure Payload Size and Binary Data Mode for Large Files
KEEP LEARNING
The Workflow Engineer connects individual n8n concepts to testing, deployment and running a complete workflow.
APPLY IT TO YOUR SYSTEM
Bring the process, the tools involved and an example of where the current workflow gets stuck.