DEV Community

Great Sage
Great Sage

Posted on

A self-hosted n8n that actually matches the 2.x architecture (SQLite + external task runners)

If you're self-hosting n8n, you've probably noticed the 2.x line changed more than the version number. The thing that actually matters operationally: n8n moved Code node execution out of the main process and into a separate task runner. Pre-2.x, "Execute Code" ran inside n8n's own Node process via a VM2-style sandbox — convenient, but it meant untrusted or buggy workflow code shared memory and a process with your whole automation server. In 2.x, that execution is handed off to a dedicated n8n-runners service that talks to the main app over a broker port. Crash a Code node and you take down the runner, not n8n itself.

That's a real architecture change, not a changelog bullet, and it means a plain "just bump the image tag" self-host setup isn't quite right anymore for 2.x — you actually need two services wired together (the runner needs N8N_RUNNERS_AUTH_TOKEN and a broker URI pointed back at the main instance), not one.

Most self-hosted n8n guides still assume the 1.x single-container shape, or jump straight to the full queue-mode stack (Postgres + Redis + worker + webhook processes) that only pays off once you're running real concurrency. For a solo user or small team running a handful of workflows, that's overkill either way — you don't need Postgres to store a few hundred workflow definitions, and you don't need queue mode until you're actually bottlenecked on execution throughput.

What this template actually runs

Two services, no database server:

  • n8n (n8nio/n8n:2.7.1) — the main app, SQLite as the backing store (N8N_USER_FOLDER=/home/node, mounted on a persistent volume so workflows/credentials/execution history survive redeploys)
  • task-runners (n8nio/runners:2.7.1) — the external Code-node execution sandbox, wired to n8n via N8N_RUNNERS_TASK_BROKER_URI and a shared auth token

Both images are set to auto-update on patch releases only (minor/major stay pinned), on a weekend + narrow weekday maintenance window — so you get security patches without a workflow silently breaking because a minor version changed behavior under you.

SQLite is a legitimate choice here, not a shortcut: n8n's SQLite backend handles the workflow/credential/execution-log write pattern fine for a single instance. The tradeoff worth knowing before you commit to it — SQLite doesn't like concurrent writers, so this setup is for one n8n instance, not a horizontally-scaled cluster. If you're running enough parallel executions that you're fighting SQLite lock contention, that's your actual signal to move to Postgres + queue mode, not a default starting point.

Deploying it

I maintain a one-click Railway template for exactly this setup — two services pre-wired, volume already mounted, auth token already shared between them so you don't have to debug the runner handshake yourself. Full disclosure: I get a kickback if you deploy through it: https://railway.com/deploy/n8n-v200-still-cheapest-regular-update?referralCode=Z1xivh&utm_medium=integration&utm_source=template&utm_campaign=devto

If you'd rather not use a referral link, the same two-service setup runs anywhere Docker/Compose does — n8nio/n8n:2.7.1 and n8nio/runners:2.7.1, wired together with N8N_RUNNERS_MODE=external, a shared N8N_RUNNERS_AUTH_TOKEN, and N8N_RUNNERS_TASK_BROKER_URI pointed at the n8n container's broker port. n8n's own docs have the full env var list for the external runner setup.

When to actually move off this

  • You need more than one n8n instance (horizontal scale, high availability) — SQLite can't do that, move to Postgres.
  • You're running enough concurrent executions that SQLite write locks start queuing workflows — same fix, Postgres + queue mode.
  • You need webhook processing decoupled from the UI/editor process for reliability — that's queue mode's actual job, not something this template does.

For everything short of that — a personal automation server, small-team workflows, API glue between a handful of services — this is the cheap, current, self-patching version of n8n without paying for infrastructure you don't need yet.

Top comments (0)