Commerce & Automation · 10 min read

n8n on Kubernetes: Queue Mode, Workers and High Availability

Main, workers and webhook processors on Kubernetes: the settings that must match across pods, how to route webhooks, and what high availability really costs.

By Praful Patel

Short answer

To run n8n reliably on Kubernetes, use queue mode: one main pod for the editor, API and triggers, a scalable pool of worker pods that execute workflows, optional webhook-processor pods for inbound traffic, and external PostgreSQL and Redis. Every pod must share the same N8N_ENCRYPTION_KEY. Workers and webhook processors scale horizontally on the free edition. Running more than one main pod (multi-main) needs an Enterprise licence.

A single n8n container works until one heavy workflow makes the editor unresponsive, or a pod restart drops in-flight executions. Queue mode fixes that by separating the process that decides what to run from the processes that run it. This guide covers the Kubernetes side: which components you need, the settings that must match across pods, how to route webhooks, how to scale workers, and what “high availability” can and cannot mean for n8n.

Designing the workflows themselves (idempotency, retries, reconciliation) is a separate topic, covered in Designing Resilient Multi-Platform Data Pipelines with n8n and Webhooks. Here the focus is the platform those workflows run on. Details reflect the n8n 2.x documentation and the official Helm chart as of October 2026.

What queue mode changes

In the default mode, one process serves the UI, receives webhooks and executes every workflow. In queue mode, production executions are handed to workers through Redis, and PostgreSQL stores workflows, credentials and execution data.

Component Started with Responsibility Replicas
Main n8n (default command) Editor UI, REST API, schedules and polling triggers, enqueuing executions 1, or several with multi-main (Enterprise)
Worker n8n worker Pulls jobs from Redis and runs workflow executions Scale horizontally
Webhook processor n8n webhook Receives production webhook calls and enqueues them Scale horizontally
Redis External service Message broker between main, webhook processors and workers Managed or HA deployment
PostgreSQL External service Workflows, credentials, execution history Managed or HA deployment

Hard requirements

PostgreSQL, not SQLite

The queue mode docs say running a distributed setup over SQLite isn’t supported. n8n’s database page lists the supported PostgreSQL majors as the latest two actively maintained versions plus one older one for compatibility. As of July 2026 that was 17 and 18, plus 16. Aurora PostgreSQL is marked experimental, and other PostgreSQL-compatible products such as AlloyDB and CockroachDB are not supported. Check the page before choosing a version, because the range moves every year.

One encryption key, everywhere

n8n encrypts stored credentials with N8N_ENCRYPTION_KEY. The main instance’s key must be shared with every worker and webhook processor. A worker with a different or auto-generated key cannot decrypt credentials, so every execution that touches them fails. Create the key once, store it in a Kubernetes Secret (or a file mounted from your secret manager), and back it up separately from the database. A database backup without the key cannot be restored into a working instance.

Binary data that every pod can read

n8n does not support filesystem binary data mode with queue mode, because a file written by one worker is not on another pod’s disk. The binary data docs say to use N8N_DEFAULT_BINARY_DATA_MODE=database. S3 external storage is the other option, but it is a paid feature: it needs a Business or Enterprise licence, and n8n will not start in s3 mode without one.

Task runners as sidecars

Code node execution runs in task runners. The task runner docs recommend external mode in production: an n8nio/runners sidecar next to each worker, with the same version as the n8n image and a shared N8N_RUNNERS_AUTH_TOKEN. Internal mode runs the runner as a child process of n8n, and the docs say it is deprecated from n8n 3.0.

The environment variables that matter

Variable Set on Purpose
EXECUTIONS_MODE=queue All n8n pods Enables queue mode
N8N_ENCRYPTION_KEY All n8n pods Must be identical everywhere
DB_TYPE=postgresdb, DB_POSTGRESDB_* All n8n pods Shared database
QUEUE_BULL_REDIS_HOST, _PORT, _PASSWORD, _DB All n8n pods Redis connection (defaults: localhost, 6379, db 0)
QUEUE_BULL_REDIS_TLS, QUEUE_BULL_REDIS_CLUSTER_NODES All n8n pods TLS and Redis Cluster seed nodes
QUEUE_HEALTH_CHECK_ACTIVE=true Workers Exposes /healthz and /healthz/readiness (DB and Redis readiness)
N8N_DISABLE_PRODUCTION_MAIN_PROCESS=true Main Stops main handling production webhooks once webhook processors exist
OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS=true Main Runs manual editor executions on workers too (default false)
N8N_GRACEFUL_SHUTDOWN_TIMEOUT Workers How long a stopping worker waits for running executions (replaces the deprecated QUEUE_WORKER_TIMEOUT)

The full list is on the queue mode environment variables page. It includes the worker lock and stalled-job intervals, which you rarely need to change.

The official Helm chart

n8n now maintains an official chart in the n8n-io/n8n-hosting repository, published to GitHub Container Registry. It requires Helm 3.12+ and Kubernetes 1.25+. Queue mode is the chart default, and the chart deliberately does not bundle PostgreSQL or Redis, so you point it at managed or separately deployed instances. Chart 1.x installs n8n 2.x. Older community charts (8gears and others) still exist, but use the official one for new deployments.

# values.yaml: keys from the official chart 1.x; check your chart version's values.yaml
queueMode:
  enabled: true
  workerReplicaCount: 2
  workerConcurrency: 10

webhookProcessor:
  enabled: true
  replicaCount: 2
  disableProductionWebhooksOnMainProcess: true

database:
  type: postgresdb
  useExternal: true
  host: n8n-postgres.internal
  port: 5432
  database: n8n
  user: n8n
  passwordSecret: { name: n8n-db-password, key: password }

redis:
  enabled: true
  useExternal: true
  host: n8n-redis.internal
  port: 6379

secretRefs:
  existingSecret: n8n-core-secrets   # holds N8N_ENCRYPTION_KEY

keda:
  enabled: true                      # requires KEDA installed in the cluster
  worker: { minReplicaCount: 2, maxReplicaCount: 20 }
helm install n8n oci://ghcr.io/n8n-io/n8n-helm-chart/n8n \
  --version <pinned-chart-version> -n n8n --create-namespace -f values.yaml

Pin the chart version and upgrade on purpose. Release 1.16.0 (14 October 2026), for example, made the chart refuse to render more than one main replica unless multi-main is enabled. That is a useful guard, but it will fail an unpinned upgrade of a cluster that was quietly running two main pods.

Routing webhooks

With webhook processors enabled, the load balancer has to split traffic by path. The n8n docs specify:

  • /webhook/* (production webhook triggers) and /webhook-waiting/* (“send and wait” resumes) go to the webhook processor Service.
  • /webhook-test/* (test URLs from the editor) and everything else go to main.

The docs also advise against adding main to the webhook pool, so that a burst of inbound calls cannot slow the editor. The chart renders a separate Ingress for webhook processors when both ingress.enabled and ingress.webhookProcessor.enabled are set. If you manage Ingress yourself, the rule looks like this:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: n8n
spec:
  ingressClassName: nginx
  rules:
    - host: n8n.example.com
      http:
        paths:
          - path: /webhook/
            pathType: Prefix
            backend: { service: { name: n8n-webhook, port: { number: 5678 } } }
          - path: /webhook-waiting/
            pathType: Prefix
            backend: { service: { name: n8n-webhook, port: { number: 5678 } } }
          - path: /
            pathType: Prefix
            backend: { service: { name: n8n-main, port: { number: 5678 } } }

Set the public base URL (WEBHOOK_URL, or webhook.url in the chart) to the external hostname. Otherwise n8n shows internal Service URLs in webhook nodes. A misrouted path usually shows up as a 404 or “Cannot POST” on production webhooks while test webhooks still work.

What high availability actually means here

Failure Without multi-main With multi-main (Enterprise)
A worker pod dies Other workers carry on; its active jobs are detected as stalled and picked up again Same
A webhook processor dies Remaining replicas take the traffic Same
The main pod dies Editor, API, schedules and polling triggers are down until Kubernetes restarts it A follower takes over leadership; the editor stays up behind sticky sessions
Redis or PostgreSQL is lost Everything stops Everything stops

Multi-main (N8N_MULTI_MAIN_SETUP_ENABLED=true) is documented as a self-hosted Enterprise feature. It needs Postgres, Redis, identical n8n versions on every main, and sticky sessions. One main is the leader and runs the at-most-once work, such as schedules. The leader key has a 10-second TTL by default. Do not try to get there by setting two main replicas without it: each main runs its own triggers, so scheduled workflows fire once per pod.

For most teams, “HA” on the free edition means redundant workers and webhook processors, managed HA Redis and Postgres, a PodDisruptionBudget, and a main pod that restarts quickly. Be honest with stakeholders that schedules pause during a main restart.

Scaling workers

Each worker runs up to --concurrency executions at once. The default is 10, and n8n recommends 5 or more. Scale on queue depth, not CPU: a worker waiting on slow HTTP calls uses little CPU while the queue grows. The chart’s KEDA integration scales workers on the length of the Redis waiting list (the chart default watches bull:jobs:wait, so change it if you set QUEUE_BULL_PREFIX).

Before you add workers, check what they call. Twenty workers with concurrency 10 can make 200 simultaneous calls to an API that allows 100 requests per 10 seconds. The downstream rate limit, not your cluster, sets the real ceiling. If you need a strict per-destination limiter, a dedicated queue in front of that API does better than n8n’s retry settings. Scaling webhook ingestion with Redis and BullMQ covers that pattern.

Operational details that bite

  • Redis eviction. n8n’s queue keys live in Redis, so a Redis that evicts keys under memory pressure can drop queued executions. Run it with maxmemory-policy noeviction, as BullMQ’s production guidance recommends for Bull-family queues, and do not share it with a cache.
  • Graceful shutdown. Set the pod’s terminationGracePeriodSeconds longer than N8N_GRACEFUL_SHUTDOWN_TIMEOUT, so Kubernetes does not kill a worker that is still finishing executions.
  • Readiness probes. Point worker readiness at /healthz/readiness, which reports database and Redis connectivity.
  • Version skew. Upgrade main, workers, webhook processors and runner sidecars together. The runners image must match the n8n version.
  • Execution data growth. Configure execution pruning. Execution history in Postgres grows quickly when workers run high volumes.

Checklist

  • External PostgreSQL on a supported major, and HA Redis with noeviction.
  • N8N_ENCRYPTION_KEY in a Secret, identical on every pod, backed up separately.
  • EXECUTIONS_MODE=queue everywhere, and binary data in database mode (or licensed S3).
  • Webhook processors behind /webhook/ and /webhook-waiting/, and main excluded from that pool.
  • External task runner sidecars with matching versions.
  • Workers autoscaled on queue depth, capped by downstream rate limits.
  • Exactly one main replica unless you hold an Enterprise licence and run multi-main.
  • Chart version pinned, and upgrades rehearsed in staging.

If one of the systems on the other end is a CRM with tight API limits, see GoHighLevel CRM sync pipelines with webhooks and workers for budgeting calls per account.

Questions people actually ask

Is n8n queue mode free, or does it need a licence?
Queue mode with workers and webhook processors is documented without a licence requirement. Multi-main setup, viewing running workers in the UI, and S3 external storage are the licensed features to watch for.

Can I run two n8n main pods for redundancy?
Only with multi-main enabled, which needs an Enterprise licence. Without it, each main pod runs its own schedules and triggers, so workflows fire twice. The official chart now refuses to render that configuration.

Is there an official n8n Helm chart?
Yes. It is maintained in the n8n-io/n8n-hosting repository and installed from oci://ghcr.io/n8n-io/n8n-helm-chart/n8n. It supports queue mode, webhook processors, HPA and KEDA, and you provide PostgreSQL and Redis yourself.

Moving n8n from a single container to Kubernetes?

I help teams plan and review n8n queue-mode deployments, from encryption key handling and webhook routing to worker scaling against real API limits.

Review your n8n deployment →
← Back to all insights