Engineering note by Jasper Tham · Updated 14 October 2026 · 7 min read

Self-hosting n8n on Kubernetes with PostgreSQL

We run n8n for our own automations on our Kubernetes cluster, backed by PostgreSQL. This is the setup that has worked for us, including the parts that are easy to get wrong.

The shape of the deployment

Two Deployments in their own namespace: n8n itself, and PostgreSQL for its data. Each gets a ClusterIP Service, and only n8n is exposed through the ingress. PostgreSQL is never reachable from outside the cluster.

Keep n8n at one replica and set the Deployment's update strategy to Recreate, so an upgrade never runs two n8n pods against the same volume at once. The main n8n process is not built to run as several identical copies; if you need more capacity, use n8n's queue mode, where the main instance hands executions to separate worker pods through Redis. Queue mode scales executions, not the main process: running several main instances (multi-main) is an Enterprise feature. We run PostgreSQL as a Deployment with its own volume, which is fine at our size; a StatefulSet, an operator or a managed database is the better long-term choice.

Use PostgreSQL, not SQLite

n8n defaults to SQLite, which is fine for trying it out. For anything you rely on, point it at PostgreSQL with DB_TYPE=postgresdb and the DB_POSTGRESDB_HOST, _PORT, _DATABASE, _USER and _PASSWORD variables. You get proper concurrent writes and normal database backups. Put the database name, user and password in a Kubernetes Secret and reference them with valueFrom, never as plain values in the manifest.

Environment variables that matter behind a proxy

  • N8N_HOST and N8N_PROTOCOL=https: the public hostname and scheme, even if TLS ends at your ingress or Cloudflare
  • WEBHOOK_URL=https://your-host/: without it, webhook nodes show internal URLs that outside services cannot reach (check the environment-variable reference for your version, as newer releases may name it N8N_WEBHOOK_URL)
  • N8N_PROXY_HOPS=1 when one reverse proxy sits in front, so n8n trusts the X-Forwarded-* headers it sends
  • GENERIC_TIMEZONE: schedule triggers use it, so set it to the timezone your schedules are written in
  • N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true: makes n8n set its settings file permissions to 0600
  • N8N_ENCRYPTION_KEY: set it explicitly from a Secret (see below)

The encryption key is the thing people lose

n8n encrypts every saved credential with an encryption key. If you do not set one, n8n generates it and stores it in /home/node/.n8n. Lose that volume and every credential in your database becomes unreadable, even though the database itself is fine. Mount a persistent volume at /home/node/.n8n, set N8N_ENCRYPTION_KEY from a Secret, and keep a copy of the key somewhere outside the cluster.

Resources and health checks

For a small team's workloads, requests of 250m CPU and 512Mi memory with limits of 500m and 1Gi have been enough for us; the PostgreSQL pod runs comfortably at 100m and 256Mi. Add readiness and liveness probes to both pods so Kubernetes restarts them if they hang, and size the n8n volume for binary data if your workflows handle files.

Access control

The n8n editor can run code and holds credentials to your other systems, so treat it like an admin panel. Use n8n's built-in user management with strong passwords, and ideally put the editor behind single sign-on or a VPN while leaving only the webhook paths public. Note that the old N8N_BASIC_AUTH_* variables were removed in n8n 1.0, so they no longer protect anything if they are still in an old manifest.

Updates and backups

Pin the image to a specific n8n version instead of latest, and upgrade deliberately after reading the release notes, because database migrations run on start-up. Back up PostgreSQL on a schedule (a CronJob running pg_dump works well), keep the encryption key with the backups, and test a restore before you need one.

Frequently asked questions

Should I use n8n Cloud or self-host n8n?

n8n Cloud is simplest if you are happy with its plans and data location. Self-hosting gives you unlimited workflows on your own infrastructure and keeps data in your environment, but you are responsible for updates, backups and security.

Can I run several n8n replicas for high availability?

Not by simply raising the replica count. Use n8n's queue mode, with Redis and separate worker pods, to scale executions.