Skip to main content
Lifetime license included with every purchase
n8n hostingn8n monitoringself-hostingdevops

n8n Production Setup: SSL, Backups, and Monitoring Done Right

Get your n8n production setup right: configure nginx SSL, PostgreSQL backups, and workflow failure monitoring. Don't run n8n in production without these.

Nn8n Marketplace Team·June 8, 2026·8 min read

Getting n8n running is a 20-minute task. Getting it production-ready takes closer to a day. The gap between "the UI loads" and a n8n production setup you'd trust with business-critical workflows is mostly invisible in tutorials — but it shows up fast when something breaks.

Three things break first: the database (SQLite can't handle concurrent writes cleanly), the process supervisor (n8n crashes and stays down), and the credential encryption key (generated ad-hoc, stored in a config file, and lost when the VPS is re-provisioned). Fix those from the start, and the rest is incremental hardening.

This guide covers the full stack: SSL termination, environment variables, backup strategy, and workflow failure monitoring. Start with the n8n Docker setup guide if you haven't done the initial install yet.

What this guide assumes

You can reach the n8n UI on a VPS or server. If you're still on SQLite and have no process supervisor, that's fine — this guide fixes both.

What breaks between dev and production

Four failure modes appear in production that you won't see locally.

SQLite write contention. SQLite's WAL (write-ahead log) gets corrupted when n8n crashes mid-write, and it doesn't handle concurrent workflow executions reliably. PostgreSQL handles both correctly. Switch databases before creating any real workflows — migrating afterward is possible but tedious.

No process supervision. Node.js doesn't restart itself after a crash. Without a systemd unit or a Docker restart policy, n8n stays down until someone notices. Silent downtime is worse than a 3 AM alert, so supervision has to be explicit from day one.

Ad-hoc encryption key. When N8N_ENCRYPTION_KEY isn't set explicitly, n8n generates one and stores it in ~/.n8n/config. If that file disappears (re-provisioning, filesystem failure, accidental deletion), every stored credential becomes unreadable. Can't be fixed without the original key.

Runaway executions. The default executionTimeout sounds generous at 3600 seconds. But it isn't enforced unless set explicitly, and workflows that hang consume resources until someone kills the process manually. Set it, and wire up error alerting so hung workflows surface instead of disappearing quietly.

SSL and the nginx reverse proxy

The standard n8n production setup puts nginx in front of n8n. n8n listens on localhost:5678; nginx terminates TLS on port 443 and proxies inbound requests.

Browser → HTTPS :443 → nginx → HTTP :5678 → n8n

Install nginx and Certbot, issue a Let's Encrypt certificate for your domain, then add a server block like this:

server {
  listen 443 ssl;
  server_name n8n.example.com;

  ssl_certificate /etc/letsencrypt/live/n8n.example.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/n8n.example.com/privkey.pem;

  location / {
    proxy_pass http://localhost:5678;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header Host $host;
    proxy_cache_bypass $http_upgrade;
    chunked_transfer_encoding on;
    proxy_buffering off;
    proxy_read_timeout 3600s;
  }
}

Two lines in that config aren't optional: proxy_buffering off and proxy_read_timeout 3600s. n8n uses server-sent events to push real-time execution updates to the UI. Without those settings, the workflow execution panel goes blank after 60 seconds and looks like the run crashed. It didn't. The proxy stopped passing events through.

Set these environment variables on the n8n process after nginx is live:

N8N_PROTOCOL=https
N8N_HOST=n8n.example.com
WEBHOOK_URL=https://n8n.example.com/
N8N_PORT=5678
Browse n8n workflow automation templates

Environment variables that matter in production

The n8n docs list dozens of environment variables. In practice, a production n8n setup needs about 12 of them set correctly. The rest are defaults you won't touch.

# Switch from SQLite immediately
DB_TYPE=postgresdb
DB_POSTGRESDB_HOST=localhost
DB_POSTGRESDB_PORT=5432
DB_POSTGRESDB_DATABASE=n8n
DB_POSTGRESDB_USER=n8n
DB_POSTGRESDB_PASSWORD=<strong-password>

# Credential encryption — set before first run, never rotate without migrating
N8N_ENCRYPTION_KEY=<32-char-random-string>
N8N_USER_MANAGEMENT_JWT_SECRET=<random>

# Execution behavior
EXECUTIONS_TIMEOUT=3600
N8N_DEFAULT_BINARY_DATA_MODE=filesystem

# Execution log retention
EXECUTIONS_DATA_SAVE_ON_ERROR=all
EXECUTIONS_DATA_SAVE_ON_SUCCESS=none
EXECUTIONS_DATA_MAX_AGE=168

The N8N_ENCRYPTION_KEY causes more data loss than any other misconfiguration in self-hosted n8n. Set it explicitly before the first workflow run. Store it in a secrets manager. Don't rely on only a .env file on the same server — if the server is gone, the credentials are gone with no recovery path.

N8N_DEFAULT_BINARY_DATA_MODE=filesystem keeps binary data (file attachments, images, large JSON responses) on disk rather than base64-encoding it into the database. Without this, a workflow that handles 50 PDF files can balloon the PostgreSQL execution_entity table by several hundred megabytes in a single day.

N8N_ENCRYPTION_KEY: the variable you can't lose

This key encrypts every credential stored in n8n. Setting it after credentials already exist requires re-encrypting the credentials table manually — there's no automated migration path. Store it in a secrets manager alongside your database password, not just in the .env file.

Backup strategy for self-hosted n8n

Production backups need a schedule and a tested restore path. Most self-hosted installs have the former. Practically none have the latter.

The two PostgreSQL tables that matter are workflow_entity and credentials_entity. The execution_entity table grows fast and contains only runtime history. Not worth including in off-site backups unless you need an audit trail.

A daily backup targeting just those two tables:

pg_dump -U n8n -d n8n -t workflow_entity -t credentials_entity \
  | gzip > /backups/n8n-$(date +%Y%m%d).sql.gz

Schedule this via cron at 2 AM, ship the compressed file to an S3-compatible bucket, and keep 30 days of history. That's a reasonable baseline for most production workflow stores.

A backup that's never been restored is a hypothesis. Test the restore path quarterly:

gunzip -c /backups/n8n-20260608.sql.gz | psql -U n8n -d n8n_test

If it fails, you want to know now, not when a real recovery is urgent. Also back up the N8N_ENCRYPTION_KEY separately from the database. The restored database won't decrypt credentials without the original key.

Minimum viable backup set

Back up the workflow_entity table, the credentials_entity table, and the N8N_ENCRYPTION_KEY. Everything else in n8n is either reconstructable or runtime state. These three items cover virtually every realistic recovery scenario.

Monitoring your n8n production setup

n8n doesn't ship with outbound failure alerting. When a workflow errors, the execution log records it, but nothing notifies anyone. On a Sunday, that means your invoice-reminder workflow can fail 40 times before anyone notices on Monday.

The pattern that works: a watchdog workflow that runs every 15 minutes, queries the n8n REST API for recent failed executions, and posts to Slack or sends email for anything that failed in the last interval.

Schedule trigger (every 15 min)
  → HTTP Request (GET /api/v1/executions?status=error&limit=25)
  → IF node (any results?)
    → Slack node: "Workflow failures in the last 15 minutes: N"

The /api/v1/executions endpoint requires an n8n API key. Generate one in Settings → n8n API, scope it read-only, and store it as a credential inside the watchdog workflow.

The AI Ops Watchtower template implements this pattern pre-built, with deduplication (so the same failure doesn't alert every 15 minutes), severity tiers for critical versus non-critical workflows, and separate Slack routing by urgency level. Worth deploying rather than building from scratch.

For server-level health checks, a cron job that curls the built-in /healthz endpoint covers uptime:

curl -sf https://n8n.example.com/healthz || \
  curl -s -X POST "$SLACK_WEBHOOK" -d '{"text":"n8n is down"}'

The /healthz endpoint returns {"status":"ok"} when the process is running and the database connection is healthy. If it doesn't, something is wrong that a workflow-level watchdog won't catch.

Key nodes for production monitoring workflows

NodePurpose
n8n-nodes-base.scheduleTrigger v1.2Fire the watchdog on a fixed interval (every 15 min)
n8n-nodes-base.httpRequest v4.2Query /api/v1/executions for recent failures
n8n-nodes-base.ifBranch on whether failed executions exist
n8n-nodes-base.code v2Format execution error details into a readable alert
n8n-nodes-base.slackRoute alerts to a Slack channel
n8n-nodes-base.gmailEmail alert fallback if Slack is down
Get the AI Ops Watchtower Template

Getting your production setup running

The practical sequence for hardening a fresh n8n install:

  1. Switch to PostgreSQL before creating any workflows. Run a test pg_dump immediately to verify the connection.
  2. Set N8N_ENCRYPTION_KEY on first launch. Store it in a secrets manager before creating any credentials.
  3. Configure nginx with the SSL block above. Test WebSocket behavior by opening a workflow and confirming the execution panel updates in real time — if it blanks at 60 seconds, the proxy headers are wrong.
  4. Add a systemd unit or Docker restart policy so n8n recovers automatically after crashes.
  5. Write the pg_dump cron job and restore it into a test database before marking backups as complete.
  6. Deploy a monitoring workflow. The AI Ops Watchtower template is the fastest path to failure alerting.
  7. Set EXECUTIONS_DATA_SAVE_ON_ERROR=all and check the error log after the first week. Silent failures show up there before they become visible anywhere else.

The Data Gatekeeper template is worth adding for workflows that process inbound data from external sources — it adds preflight validation and structured failure routing before data touches the main pipeline, which reduces the volume of hard-to-diagnose runtime errors.

For more on building operational automation around your infrastructure, the n8n DevOps automation guide covers deployment pipelines, infrastructure alerting, and using n8n to bridge your CI/CD and notification systems.

A production n8n setup isn't dramatically harder than a dev install. Most of the surface area comes down to five decisions: PostgreSQL instead of SQLite, explicit encryption key, nginx proxy with correct headers, scheduled backups with tested restores, and a monitoring workflow that alerts on failures. Get those five right before the first real workflow runs.

Browse all n8n workflow templates
FAQ

Common questions

What's the minimum server spec for n8n in production?
A 2-core, 4 GB RAM VPS handles a standard n8n production setup. Queue mode with a separate worker process needs at least 4 GB, ideally 8 GB. Memory matters more than CPU — the Node.js process and PostgreSQL compete for RAM under high-frequency workflow execution.
How do I set up SSL for a self-hosted n8n instance?
The standard pattern is an nginx reverse proxy terminating TLS on port 443 and proxying to n8n on localhost:5678. Set N8N_PROTOCOL=https and N8N_HOST to your domain. Let's Encrypt and Certbot handle certificate generation. Without proxy_buffering off in nginx, the execution-progress panel blanks out after 60 seconds.
Can I recover n8n workflows if the server crashes?
Yes, with a proper backup. The critical tables are workflow_entity and credentials_entity in PostgreSQL. A daily pg_dump of those two tables, stored off-site, is enough to restore all workflows and credentials. The N8N_ENCRYPTION_KEY must also be backed up — losing it makes stored credentials unreadable even with the database intact.
Stop reading. Start running.

Get the workflow templates this guide is built on

Import-ready n8n JSON, step-by-step setup, and tested end-to-end. One-time payment, own it forever.