Introduction

  • TL;DR: This post focuses on production-grade n8n self-hosting. We cover Docker Compose templates (single & queue mode), Postgres/Redis, reverse proxy TLS, webhook URL correctness, backups, and monitoring.
  • In practice, most self-hosting incidents come from URL/webhook mismatch, lost encryption keys, and runaway execution data growth. We’ll harden those first.

1) Design decisions that matter in production

n8n defaults to SQLite for credentials, executions, and workflows, and supports Postgres for self-hosted setups. n8n’s database environment variable docs also state that MySQL/MariaDB support was deprecated in v1.0, so Postgres is the safe default for new deployments.

DecisionOptionsRecommended for production
DatabaseSQLite / PostgresPostgres
Execution modeDefault / Queue modeQueue if you need scaling
TLS / Reverse proxyTraefik / Nginx / LBStandardize on one
Data retentionDefaults / Tuned pruningTune explicitly

Why it matters: Production issues are usually operational (persistence, security, observability), not workflow logic. Locking these early prevents recurring incidents.

2) Template #1: Fast “production-ish” start (Official Docker Compose + TLS)

The official Docker Compose guide runs n8n on Linux using Docker Compose and shows an example with n8n + Traefik for TLS and routing. It also explains where n8n stores state (e.g., /home/node/.n8n on a volume).

Minimal .env additions you almost always want behind a proxy:

1
2
3
4
N8N_PROTOCOL=https
N8N_HOST=n8n.example.com
N8N_PORT=5678
WEBHOOK_URL=https://n8n.example.com/

These variables are documented in n8n’s deployment/endpoint environment variables reference.

Why it matters: If webhook URLs are wrong behind a proxy, third-party callbacks fail and the editor UI may generate incorrect URLs.

3) Template #2: Postgres + Redis Queue mode (scalable baseline)

3.1 Postgres variables (minimum set)

n8n documents Postgres settings like DB_TYPE=postgresdb plus host/user/password/schema variables.

1
2
3
4
5
6
7
DB_TYPE=postgresdb
DB_POSTGRESDB_HOST=postgres
DB_POSTGRESDB_PORT=5432
DB_POSTGRESDB_DATABASE=n8n
DB_POSTGRESDB_USER=n8n
DB_POSTGRESDB_PASSWORD=change-me
DB_POSTGRESDB_SCHEMA=public

Why it matters: Execution history and binary data can grow quickly; Postgres is far more robust for backups and operations than SQLite for sustained workloads.

4) Queue mode: Redis settings you must wire correctly

Queue mode environment variables include Redis host/port/password and related settings.

1
2
3
4
EXECUTIONS_MODE=queue
QUEUE_BULL_REDIS_HOST=redis
QUEUE_BULL_REDIS_PORT=6379
QUEUE_BULL_REDIS_PASSWORD=change-me

For scaling concepts and the queue-mode model, see n8n’s “Configuring queue mode” documentation.

Why it matters: Queue mode is the path to horizontal scaling: you can decouple UI/API from execution throughput.

5) Practical Docker Compose example (baseline)

Below is a pragmatic example composed from the officially documented environment variables (DB, queue, endpoints, encryption, pruning, metrics).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
services:
  postgres:
    image: postgres:16
    environment:
      POSTGRES_DB: n8n
      POSTGRES_USER: n8n
      POSTGRES_PASSWORD: change-me
    volumes:
      - postgres_data:/var/lib/postgresql/data

  redis:
    image: redis:7
    command: ["redis-server", "--requirepass", "change-me"]
    volumes:
      - redis_data:/data

  n8n:
    image: docker.n8n.io/n8nio/n8n
    ports:
      - "5678:5678"
    environment:
      - N8N_PROTOCOL=https
      - N8N_HOST=n8n.example.com
      - N8N_PORT=5678
      - WEBHOOK_URL=https://n8n.example.com/

      - N8N_ENCRYPTION_KEY=replace-with-32+chars-secret

      - DB_TYPE=postgresdb
      - DB_POSTGRESDB_HOST=postgres
      - DB_POSTGRESDB_PORT=5432
      - DB_POSTGRESDB_DATABASE=n8n
      - DB_POSTGRESDB_USER=n8n
      - DB_POSTGRESDB_PASSWORD=change-me

      - EXECUTIONS_MODE=queue
      - QUEUE_BULL_REDIS_HOST=redis
      - QUEUE_BULL_REDIS_PORT=6379
      - QUEUE_BULL_REDIS_PASSWORD=change-me

      - EXECUTIONS_DATA_PRUNE=true
      - EXECUTIONS_DATA_MAX_AGE=336
      - EXECUTIONS_DATA_PRUNE_MAX_COUNT=10000

      - N8N_METRICS=true
      - N8N_METRICS_INCLUDE_QUEUE_METRICS=true

      - N8N_DEFAULT_BINARY_DATA_MODE=database

    volumes:
      - n8n_data:/home/node/.n8n
    depends_on:
      - postgres
      - redis

volumes:
  postgres_data:
  redis_data:
  n8n_data:

Key operational facts:

  • Execution pruning is enabled by default, with documented default thresholds (age/count) and tuning knobs.
  • Prometheus metrics are disabled by default and enabled via environment variables.
  • In queue mode, n8n does not support filesystem binary data mode; use database instead.

Why it matters: This baseline prevents three common incidents: lost encryption key → unrecoverable credentials, unbounded execution growth → disk exhaustion, and proxy/webhook mismatch → broken integrations.

6) Never lose N8N_ENCRYPTION_KEY

n8n supports setting a custom encryption key, and the official Compose guide explains where n8n stores state (including keys) on mounted volumes.

Why it matters: Losing or rotating the key unintentionally can make stored credentials unusable.

7) Execution data retention: tune it

n8n recommends reducing unnecessary stored execution data and enabling pruning; pruning defaults and variables are documented.

Why it matters: Retention is a capacity-planning knob. Without it, storage incidents are inevitable.

8) Monitoring: Prometheus metrics (including queue metrics)

n8n exposes Prometheus metrics when enabled; queue metrics can be included with a separate flag.

1
curl -s http://localhost:5678/metrics | head

Why it matters: Visibility into queue depth and throughput makes scaling decisions (more workers, higher resources) data-driven.

9) Backups: export workflows via CLI as a fast recovery path

n8n documents CLI export/import commands for workflows and credentials.

Why it matters: A workflow export is often the fastest “restore service” lever during incidents or migrations.

10) TLS automation note (Let’s Encrypt HTTP-01 uses port 80)

Let’s Encrypt documents that HTTP-01 validation can only be done on port 80, per ACME requirements. The official n8n Compose example emphasizes HTTPS-only access in that setup.

Why it matters: Getting TLS automation right avoids certificate-expiry outages.

Conclusion

  • Use the official Compose (with TLS proxy) to start quickly, then move to Postgres + queue mode when scaling matters.
  • Treat WEBHOOK_URL, N8N_ENCRYPTION_KEY, and execution retention/pruning as first-class operational configuration.
  • Enable metrics and keep a workflow export path for faster recovery.

Summary

  • Production self-hosting is mostly about persistence, URL correctness, encryption keys, and retention.
  • Postgres is the safe DB baseline; MySQL/MariaDB are deprecated as of v1.0.
  • Queue mode + Redis is the scaling lever; tune execution retention early.
  • Prometheus metrics + CLI exports improve incident response time.

#n8n #dockercompose #selfhosting #postgresql #redis #queuemode #reverseproxy #traefik #nginx #prometheus

References

  • (Docker-Compose, 2026-01-06)[https://docs.n8n.io/hosting/installation/server-setups/docker-compose/]
  • (Supported databases and settings, 2026-01-06)[https://docs.n8n.io/hosting/configuration/supported-databases-settings/]
  • (Database environment variables, 2026-01-06)[https://docs.n8n.io/hosting/configuration/environment-variables/database/]
  • (Endpoints environment variables, 2026-01-06)[https://docs.n8n.io/hosting/configuration/environment-variables/endpoints/]
  • (Queue mode environment variables, 2026-01-06)[https://docs.n8n.io/hosting/configuration/environment-variables/queue-mode/]
  • (Configuring queue mode, 2026-01-06)[https://docs.n8n.io/hosting/scaling/queue-mode/]
  • (Execution data, 2026-01-06)[https://docs.n8n.io/hosting/scaling/execution-data/]
  • (Set a custom encryption key, 2026-01-06)[https://docs.n8n.io/hosting/configuration/configuration-examples/encryption-key/]
  • (Scaling binary data in n8n, 2026-01-06)[https://docs.n8n.io/hosting/scaling/binary-data/]
  • (Enable Prometheus metrics, 2026-01-06)[https://docs.n8n.io/hosting/configuration/configuration-examples/prometheus/]
  • (Challenge Types, 2026-01-06)[https://letsencrypt.org/docs/challenge-types/]