Task Runners: Running Code Nodes More Securely
n8n Task Runners execute Code nodes in isolation instead of the main process. Here is how internal and external mode work.
Task Runners are an n8n feature that no longer executes JavaScript and Python code from the Code node in the main n8n process, but in a separate, isolated process or container. This protects the rest of the n8n instance from faulty or unwanted code in a workflow accessing environment variables, the file system, or other running workflows. Since version 1.111.0, the external, fully isolated mode can be used in production; the internal mode (execution as a child process with the same permissions as n8n) is explicitly not considered production ready according to the n8n documentation. As of: July 2026.
Why running code directly in the main process is a risk
Until recently, n8n executed code from the Code node directly in the same process in which the rest of the workflow engine runs. This is simple to implement, but risky: a script with access to Node.js built-ins can theoretically access environment variables, the file system, or other resources of the n8n instance that actually have nothing to do with the individual workflow. Task Runners solve this problem by moving code execution out of the main process. According to the n8n documentation, the principle is a generic mechanism for executing tasks in a secure and performant way, specifically for user-controlled JavaScript and Python code in the Code node. Three components work together: the Task Runner, which actually executes the code, the Task Broker, which is part of the n8n main instance or a worker and coordinates communication, and the Task Requester, meaning the Code node itself, which requests an execution. Communication runs over WebSocket connections: the runner fetches tasks from the broker and returns the results.
Internal versus external mode compared
n8n distinguishes between two operating modes. In internal mode, the default setting via N8N_RUNNERS_MODE=internal, n8n starts the Task Runner as a child process with the same user and group ID as the main instance. This somewhat reduces the risk compared to the old inline execution, but according to the documentation it offers no real isolation and is explicitly not recommended for production environments. In external mode, a separate launcher application takes over the runners in their own containers, usually as a sidecar container with the image n8nio/runners next to the actual n8n instance. Every worker in queue mode needs its own sidecar, as do main instances that process manual executions themselves. Important for operation: the version of the n8nio/runners image must match the n8n version, and external Task Runners require at least n8n 1.111.0.
Hardening with isolated containers
Anyone running external mode in production can, according to the n8n hardening documentation, apply additional protective measures. These include a distroless Docker image with the tag suffix -distroless without a package manager and shell, running as the unprivileged nobody user with user and group ID 65532, a read-only root file system with a minimal emptyDir volume for /tmp, and an AppArmor profile that blocks access to /proc files such as environ and mounts, preventing code in the node from reading environment variables or mount information. Together, these measures result in a significantly tighter sandbox for Code nodes compared to the old execution in the main process.
Key environment variables at a glance
- N8N_RUNNERS_MODE: internal (default) or external, controls the operating mode.
- N8N_RUNNERS_AUTH_TOKEN: shared secret that a Task Runner uses to authenticate with n8n.
- N8N_RUNNERS_BROKER_PORT: port of the Task Broker, default 5679.
- N8N_RUNNERS_BROKER_LISTEN_ADDRESS: address on which the broker listens, default 127.0.0.1, usually set to 0.0.0.0 for external containers.
- N8N_RUNNERS_MAX_CONCURRENCY: number of concurrent tasks per runner, default 5.
- N8N_RUNNERS_TASK_TIMEOUT: maximum runtime of a task in seconds, default 300, after which the runner restarts.
- NODE_FUNCTION_ALLOW_BUILTIN and NODE_FUNCTION_ALLOW_EXTERNAL: allowlist for permitted Node.js modules in the Code node.
- N8N_RUNNERS_STDLIB_ALLOW and N8N_RUNNERS_EXTERNAL_ALLOW: corresponding allowlists for the Python standard library and third-party modules.
- N8N_BLOCK_RUNNER_ENV_ACCESS: blocks Python code by default (true) from accessing the runner's environment variables.
Who should switch
Task Runners primarily concern self-hosted n8n instances with Docker or Kubernetes, where Code nodes from different teams or with sensitive credentials run in the same instance. Anyone running only a few of their own trusted workflows gains less, but should still keep external mode in mind, because n8n marks the N8N_RUNNERS_ENABLED variable as deprecated from version 2.0 onward and the old inline operation will foreseeably disappear. Honestly, external mode means additional operational effort: another container per worker, a matching image version, and its own allowlists for modules. Anyone who wants to avoid this effort will stay on internal mode for now, but should be aware that, according to n8n itself, it is not a production standard. For companies that use n8n as a central automation platform and pay attention to German data sovereignty and traceable operational security, a deliberate decision for external mode is worthwhile. NordFlux supports the setup and hardening of n8n instances, see n8n consulting.
Frequently asked questions about Task Runners in n8n
What is the difference between internal and external Task Runner mode?
In internal mode, the Task Runner runs as a child process of n8n with the same permissions; in external mode, it runs in its own container and, according to the n8n documentation, is fully isolated from the main process. Only external mode is considered production ready.
From which n8n version do external Task Runners work?
External Task Runners require, according to the documentation, at least n8n 1.111.0; in addition, the version of the n8nio/runners image must match the n8n version in use.
Do I need a separate Task Runner container for every worker?
Yes, in queue mode every worker needs its own sidecar container. Main instances that process manual executions themselves also need their own runner according to the documentation, unless OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS is enabled.
Do Task Runners automatically block access to environment variables?
For Python code, access to the runner's environment variables via N8N_BLOCK_RUNNER_ENV_ACCESS is blocked by default. For isolation at the operating system level, n8n additionally recommends measures such as an AppArmor profile that prevents access to /proc files.
Sources: n8n documentation: Set up task runners and n8n documentation: Harden task runners.
NordFlux UG (haftungsbeschränkt)
NordFlux builds digital employees for organisations: automations and AI agents that take over repetitive work. You stay in control.
Concrete questions about automation or AI?
In a free initial analysis we discuss your case directly. No strings attached.