What Are Expressions in n8n
n8n expressions let you reference data dynamically instead of hardcoding values. When you connect nodes together, data flows from one node to the next as JSON objects. Expressions give you a way to reach into that JSON and pull out exactly the value you need — or transform it before passing it along.
Every expression in n8n is wrapped in double curly braces. Inside those braces you write JavaScript-compatible code, and n8n evaluates it at runtime when the workflow executes.
That expression reads the email field from the current node's input data. Simple, but this pattern is the foundation of everything you will do with data mapping.
Key Variables You Will Use Every Day
n8n exposes several built-in variables inside expressions. Knowing these three covers the vast majority of real workflows.
The first is $json, which refers to the current item's data object. If a previous node returned a user record, $json.name gives you the user's name field.
The second is $node, which lets you reach back to any named node in the workflow. This is useful when you need data from a node that is not the immediate predecessor.
The third is $now, which returns the current timestamp as a Luxon DateTime object. You can call Luxon methods directly on it.
n8n bundles Luxon for date manipulation and also exposes the full JavaScript standard library, so string methods, Math, and JSON utilities all work inside expressions.
Transforming Data With Expressions
Expressions are not just for reading values — you can transform them inline. Common patterns include string concatenation, number formatting, conditionals, and array operations.
Building a full name from two fields:
A simple conditional to set a fallback value when a field might be missing:
Formatting a date coming in as a Unix timestamp:
The Set node is the most natural place to use these expressions. Add it between two nodes whenever you need to rename fields, combine values, or drop fields you do not need downstream.
Mapping Data Between Nodes
Data mapping means wiring the output of one node to the input of another. In the n8n UI you can drag a field directly onto a target parameter, and n8n writes the expression for you. But understanding what it generates helps you fix it when something goes wrong.
When a node returns multiple items, $json refers to each item individually as n8n iterates. So if your previous node returned 50 rows, every expression is evaluated 50 times — once per item. This is the default behavior and requires no extra configuration.
If you need to aggregate all items into one structure — for example, to build an array of emails from all rows — use the Code node with $input.all().
The Code node runs full JavaScript and is the right tool when an expression inside a field parameter becomes too complex to read.
Common Mistakes and How to Avoid Them
The most frequent error is referencing a field that does not exist, which returns undefined and can silently break downstream nodes. Always use the expression editor's preview panel — it shows the resolved value before you save.
A second common issue is forgetting that $json refers to the current node's input, not its output. If you are inside a Set node and want data from two steps back, use $node["NodeName"].json instead.
A third mistake is treating $now as a plain string. It is a Luxon object, so comparing it directly to a date string will not work. Convert both sides to the same type first.
Summary
Expressions are how n8n workflows become dynamic. The core pattern — double curly braces around a JavaScript expression reading from $json, $node, or $now — handles most scenarios. Use the Set node for straightforward field mapping and renaming, and escalate to the Code node when logic grows complex. Always verify expressions in the preview panel before running a live workflow.
Lesson Checkpoint
Review what you learned and get feedback on your work.