Artur
Artur
Founder

n8n Kubernetes Deployment: Helm Chart Setup Guide (2026)

June 22, 2026

n8n-kubernetesn8n-helm-chartn8n-k8sself-hostingqueue-mode

TL;DR: Use the community Helm chart (8gears/n8n-helm-chart) for almost every n8n on Kubernetes deployment. It handles the worker pods, webhook pods, Valkey/Redis, persistence, and ingress that you would otherwise hand-write across six or seven YAML files. There is no official n8n Helm chart; n8n ships only raw example manifests in the n8n-io/n8n-hosting repo, which are fine for learning but tedious to operate. Reach for raw manifests only when you need full control or have policies that forbid third-party charts. And if you are a single team running a handful of workflows, Kubernetes is probably overkill - a Docker Compose box will serve you better and cost less to babysit.

Should you even use Kubernetes for n8n?

Kubernetes earns its complexity when you need to scale execution horizontally, survive node failures, and run n8n alongside an existing cluster you already operate. If none of those are true, you are paying the Kubernetes tax for nothing.

The honest decision rule: if a single VM running Docker Compose with Postgres handles your load and you do not already run a cluster, stay there. n8n in regular mode is a single Node process - it does not get faster by living in a pod. You only benefit from k8s once you split execution into separate worker pods (queue mode), at which point the orchestration, autoscaling, and self-healing start paying for themselves.

Where Kubernetes wins for n8n:

  • You already run a cluster and want n8n to inherit its ingress, secrets, monitoring, and backup tooling.

  • You need queue mode with several worker replicas and want autoscaling to add or drop workers under load.

  • You want zero-downtime upgrades and automatic restart of crashed pods without a human on call.

If you are running fewer than a few thousand executions a day and have one server, the maintenance burden of a cluster will outweigh the benefits. Kubernetes does not make n8n more reliable on its own; it makes a correctly-architected multi-pod n8n more reliable.

The two ways to deploy: raw manifests vs the Helm chart

There is no official n8n Helm chart. n8n publishes example Kubernetes manifests in the n8n-io/n8n-hosting repository, and the maintained community chart is 8gears/n8n-helm-chart. Get this distinction right before you start, because most "n8n helm chart" search results blur the two.

The raw manifests in n8n-io/n8n-hosting are a teaching tool. They give you a PersistentVolumeClaim, a Deployment, a Service, and a Postgres pair, and they are great for understanding what n8n actually needs on a cluster. They are not great for day-two operations: every change is a hand-edit, there is no templating, and queue mode is left as an exercise for you.

The 8gears chart is what you should run in production unless a specific constraint stops you. It templates main, worker, and webhook deployments from one values.yaml, can pull in Valkey (a Redis-compatible server) as a dependency for queue mode, wires up ingress and TLS, and exposes n8n config through structured values rather than a wall of raw env vars.

Use raw manifests instead of the chart only when: your org forbids third-party Helm charts, you need a manifest shape the chart cannot template, or you are deliberately learning the moving parts. Otherwise the chart saves you from re-implementing everything it already solved.

What n8n actually needs on the cluster

Every n8n Kubernetes deployment, chart or not, comes down to four building blocks.

A persistent volume for ~/.n8n. n8n stores its encryption key (config file) and SQLite database here if you have not moved to Postgres. The official example mounts a PersistentVolumeClaim into the n8n container so this directory survives pod restarts. Lose that volume without a Postgres backend and you lose the encryption key that decrypts your credentials. The container runs as the node user, so the mounted directory is the user's home .n8n path inside the image.

Postgres for workflow and execution data. SQLite on a single PVC works for a demo, but on a cluster you want Postgres so multiple pods can share one database. The official manifests ship a postgres-deployment.yaml, postgres-service.yaml, and postgres-secret.yaml and back Postgres with its own PVC. In production, prefer a managed database (Cloud SQL, RDS, a Postgres operator) over a single in-cluster Postgres pod, because that pod becomes a single point of failure.

Redis for queue mode. Once you split execution into worker pods, n8n uses Redis (BullMQ) as the job queue. The main process pushes executions onto the queue; workers pull them off. No Redis, no queue mode.

A Service plus Ingress for traffic. n8n listens on port 5678. The example manifests expose it with a Service of type LoadBalancer; in most clusters you front it with an Ingress and a TLS certificate instead. Postgres sits behind its own internal Service on 5432 and should never be exposed publicly.

Deploying with the 8gears Helm chart

The chart is distributed as an OCI artifact, so there is no helm repo add for the modern releases - you install straight from the registry.

helm install n8n oci://8gears.container-registry.com/library/n8n \
  --version 2.0.1 \
  --namespace n8n \
  --create-namespace \
  -f values.yaml

Pin --version explicitly. Letting Helm grab "latest" is how you get surprised by a breaking values change on the next deploy.

A minimal single-instance values.yaml with Postgres and persistence looks like this:

image:
  repository: n8nio/n8n
  pullPolicy: IfNotPresent
  # tag defaults to the chart's appVersion; pin it for reproducible deploys
  tag: "1.70.0"

main:
  replicaCount: 1
  persistence:
    enabled: true
    type: dynamic
    storageClass: standard
    size: 2Gi
  config:
    n8n:
      host: n8n.example.com
      protocol: https
    db:
      type: postgresdb
      postgresdb:
        host: postgres.databases.svc.cluster.local
        port: 5432
        database: n8n
        user: n8n
  secret:
    db:
      postgresdb:
        password: "set-via-secret-or-extraEnv"
  service:
    type: ClusterIP

ingress:
  enabled: true
  className: nginx
  hosts:
    - host: n8n.example.com
      paths:
        - path: /
          pathType: Prefix
  tls:
    - secretName: n8n-tls
      hosts:
        - n8n.example.com

A few things worth knowing about the chart's shape. The main, worker, and webhook sections share the same structure (config, secret, replicaCount, persistence, resources, autoscaling), which makes the values file predictable once you learn one section. The main.config block is converted into n8n environment variables, so anything in the n8n env var reference maps into it. The chart's pod security context runs as non-root user 1000 by default, which matters if you bring your own storage and need to match file ownership. Persistence defaults to off, so you must set main.persistence.enabled: true or you will lose your encryption key on the first restart.

The chart does not bundle Postgres. You point it at an external database (managed or in-cluster). It can bundle Valkey for Redis, which you enable when you turn on queue mode.

Enabling queue mode with worker pods

Queue mode is the entire reason to run n8n on Kubernetes, and it is where the chart pulls ahead of raw manifests. In queue mode you set EXECUTIONS_MODE=queue, run a Redis instance, and start one or more processes with the n8n worker command. The main pod handles the UI and queues jobs; worker pods execute them. We cover the architecture and tuning in depth in the queue mode and Redis scaling guide - this section is just the Kubernetes wiring.

In the 8gears chart, you turn on scaling, enable Valkey for the queue, and enable worker pods:

scaling:
  enabled: true
  redis:
    host: "        # leave empty to use the bundled Valkey service
    password: "

valkey:
  enabled: true     # deploys a Valkey (Redis) service for the queue

worker:
  enabled: true
  replicaCount: 3
  concurrency: 10
  resources:
    requests:
      memory: 256Mi
    limits:
      memory: 512Mi

webhook:
  enabled: true     # optional: dedicated pods for inbound webhooks
  replicaCount: 2

With this, the chart deploys a main pod, three worker pods each running n8n worker with a concurrency of 10, an optional pair of webhook pods, and a Valkey service. Under the hood the workers connect to Redis via QUEUE_BULL_REDIS_HOST and QUEUE_BULL_REDIS_PORT (default 6379); the chart sets these from your scaling.redis values or the bundled Valkey. Set QUEUE_HEALTH_CHECK_ACTIVE=true on workers so Kubernetes can probe their health endpoint and restart unhealthy pods.

Dedicated webhook pods are optional. Enable them when inbound webhook volume is high enough that you want it isolated from the main process; for most setups, letting the main pod handle webhooks is fine until you measure a problem.

Autoscaling workers

The chart exposes worker.autoscaling.enabled to attach a HorizontalPodAutoscaler. Scaling workers on CPU is a blunt instrument for n8n, because a worker waiting on a slow HTTP call is idle on CPU while still holding a job. If you autoscale, watch real execution latency and queue depth, not just CPU, and treat the HPA as a coarse safety net rather than a precise dial. Often a fixed replicaCount sized to your peak is simpler and more predictable.

The raw-manifest path, if you must

If policy or curiosity sends you to raw manifests, clone n8n-io/n8n-hosting and start from the Kubernetes folder. The pieces you will apply:

  • n8n-claim0-persistentvolumeclaim.yaml - the PVC for the n8n home directory.

  • postgres-secret.yaml and n8n-secret.yaml - credentials and the n8n encryption key.

  • postgres-deployment.yaml plus postgres-service.yaml - the database on port 5432.

  • n8n-deployment.yaml plus n8n-service.yaml - n8n itself on port 5678.

  • storage.yaml - the StorageClass, if your cluster needs one defined.

The example deployment sets conservative resources - requests.memory: "250Mi" and limits.memory: "500Mi" per container - and lets Kubernetes manage CPU. Those numbers are a starting point for a quiet instance; bump the limits well past 500Mi before running real workflows, especially anything that processes large payloads or binary data, or you will hit OOMKills.

The example n8n-service.yaml uses a LoadBalancer. For anything real, replace it with a ClusterIP Service behind an Ingress so you control TLS and routing centrally. The same proxy header pitfalls that bite Docker users apply here: get your ingress headers wrong and webhooks fail in production while testing looks fine. Our n8n reverse proxy and SSL guide covers the exact headers that break n8n webhooks behind a proxy - the lesson transfers directly to an Ingress controller.

The honest cost of this path: queue mode means hand-writing worker and webhook deployments, a Redis deployment and service, and the full set of queue env vars across each. That is precisely the work the chart automates. Going raw to "keep it simple" usually produces more YAML, not less.

Ingress and TLS

Front n8n with an Ingress and a real certificate; do not expose port 5678 directly. A typical nginx-ingress setup uses cert-manager to issue and renew TLS, with the certificate stored in a Secret the Ingress references.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: n8n
  namespace: n8n
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
    nginx.ingress.kubernetes.io/proxy-body-size: "16m"
spec:
  ingressClassName: nginx
  tls:
    - hosts:
        - n8n.example.com
      secretName: n8n-tls
  rules:
    - host: n8n.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: n8n
                port:
                  number: 5678

Set proxy-body-size generously if your workflows accept large file uploads through webhooks; the default Ingress body limit will reject big payloads with a 413. Make sure n8n's N8N_HOST and N8N_PROTOCOL (or WEBHOOK_URL) match the public hostname, or the webhook URLs n8n generates will point at the wrong place.

Common mistakes that bite on day two

Persistence left disabled. The chart defaults persistence.enabled to false. Skip it and the first pod reschedule wipes ~/.n8n, including the encryption key, making every stored credential undecryptable. Always enable persistence on the main pod, and always set a stable N8N_ENCRYPTION_KEY via a Secret so a fresh volume does not generate a new key.

One in-cluster Postgres pod as your production database. It is a single point of failure with no automatic failover. Use a managed Postgres or a proper operator for anything you care about.

Treating CPU autoscaling as queue management. Workers blocked on network calls look idle to the HPA. Size for peak or autoscale on queue-aware signals.

Mismatched host config. If N8N_HOST does not match your Ingress hostname, the UI loads but webhooks and OAuth callbacks break. Set it explicitly.

When this is more than you want to run

Kubernetes is the right tool when you already operate a cluster and need n8n to scale and self-heal alongside it. It is the wrong tool when you are reaching for it to make a small n8n instance feel "production grade" - a single Docker host with Postgres and good backups is more reliable for that case, and far cheaper to keep healthy.

If you have read this far and are weighing whether the cluster, the queue-mode wiring, and the day-two operations are worth your team's time versus shipping the automations themselves, that tradeoff is exactly where an outside hand helps. We do n8n architecture and self-hosting setups, including queue-mode-on-Kubernetes deployments, and are happy to look at your specific scale before you commit to the heavier path. No pressure either way - the Docker Compose route is genuinely the right answer for most teams.

FAQ

Is there an official n8n Helm chart?

No. n8n provides example raw Kubernetes manifests in the n8n-io/n8n-hosting repository, but the maintained Helm chart is the community 8gears/n8n-helm-chart. For production use the 8gears chart unless a policy forbids third-party charts.

Does the 8gears chart include Postgres and Redis?

It can bundle Valkey (a Redis-compatible server) for queue mode, which you enable with valkey.enabled: true. It does not bundle Postgres - you point main.config.db.postgresdb at an external or in-cluster database. Using a managed Postgres is the recommended setup.

Do I need Kubernetes to run n8n in queue mode?

No. Queue mode runs anywhere you can run a main process, worker processes (n8n worker), and Redis, including Docker Compose. Kubernetes adds value when you want autoscaling, self-healing, and orchestration of those worker pods, not as a requirement for queue mode itself.

What does n8n store in the persistent volume?

The ~/.n8n directory holds the encryption key used to decrypt stored credentials and, if you have not moved to Postgres, the SQLite database. Lose this volume without an external database and you lose access to your credentials. Enable persistence and pin a stable N8N_ENCRYPTION_KEY.

How many worker replicas should I run?

Start with a small fixed count (two or three) sized to your observed peak, each with a concurrency around 10, then adjust based on queue depth and execution latency rather than CPU alone. Many production setups are better served by a fixed replica count than by aggressive CPU-based autoscaling.

Can I expose n8n with a LoadBalancer Service instead of Ingress?

You can, and the official example does, but for real deployments use an Ingress with TLS so you manage certificates and routing centrally. Keep Postgres on an internal ClusterIP Service and never expose port 5432 publicly.


n8n Kubernetes Deployment: Helm Chart Setup Guide (2026) | n8nlogic