n8n-code-nodes
n8n Code Nodes
The Code node is powerful and often the wrong tool. The n8n equivalent of dropping into raw SQL when an ORM would do: real cases exist, but the moment a Code node handles logic an expression could, the workflow is harder to read, debug, and maintain. There's also a real perf gap: Code runs in a sandboxed JS runtime, expressions and Edit Fields run in-process, and the per-invocation overhead can be hundreds of times higher in Code (anecdotally ~2ms vs ~600ms for equivalent logic). For hot paths and large item counts, that compounds.
Strong defaults
-
Code node is a last resort. Decision order: expression (
{{...}}) → arrow function inside Edit Fields → Code node. The first two paths cover most "transform this data" tasks. Code earns its place for multi-source aggregation, external libraries, stateful work (getWorkflowStaticData), and a few specific patterns documented below. -
Default to JavaScript. Write JS unless the user explicitly asked for Python ("use Python here," "I'm a Python shop," pasted Python code). Everywhere else in n8n (expressions, Edit Fields) is JS, JS has a curated library allowlist (
lodash,crypto,luxon).
Decision tree
Need custom logic?
├── Is it a transformation of one or two fields?
│ └── Expression: {{ $json.foo.toUpperCase() }} or {{ $json.items.map(item => item.name).join(', ') }}
│ Most "just transform this" cases land here.
│
├── Is it multi-line, but pure data shaping (map, filter, reduce, conditional)?
More from n8n-io/skills
n8n-loops
Use when working with multi-item data, batches, paginated APIs, rate-limited APIs, anything that needs to "do this for each", or any time the user mentions looping, iterating, batching, paging, or "loop over items". Triggers on "loop", "iterate", "for each", "batch", "page through", "paginate", "rate limit", "process all", or any node that should run once vs once-per-item.
5n8n-connections
Use when writing or reviewing n8n SDK code that wires IF, Switch, Merge, error outputs, or any multi-input/multi-output connection. Triggers on .add(), .to(), .input(n), .output(n), .onTrue, .onFalse, .onCase, .onError, useDataOfInput, merge, switch, IF nodes, error branches, fan-out, fan-in, or any review of the workflow's connections object.
3n8n-expressions
Use when writing or reviewing n8n expressions (`{{...}}` syntax), `$json` / `$node` references, Luxon date code, or expression errors. Triggers on `{{}}`, `$json`, `$node`, `$input`, `DateTime`, `Luxon`, "expression error", "evaluating", "format date", "transform field", or any node-parameter assignment.
3n8n-debugging
Use when an n8n workflow isn't working, errors appear, results don't match what was expected, or the user says "this isn't working." Triggers on errors, unexpected output, "it's not working", "why is this happening", "the workflow stopped", failure investigation, or any debugging context.
3n8n-data-tables
Use when working with n8n's built-in Data Tables, designing schemas, inserting/updating/upserting rows, deduping, or querying. Triggers on "Data Table", "data table", `n8n-nodes-base.dataTable`, "dedup", "idempotency", "lookup", "persistent state", "store across executions", or any schema design discussion inside n8n.
3n8n-binary-and-data
Use when handling files, images, attachments, or binary data in n8n, OR when an AI agent needs to take a user-uploaded file as tool input or return a generated file. For Data Tables (schemas, dedup, persistent state), see the separate n8n-data-tables skill. Triggers on "file", "image", "PDF", "attachment", "binary", "upload", "download", chat trigger with files, agent tool that needs a file, vision/multimodal, or any handling of non-JSON file data.
3