Chapter 9

What an item is, and how data moves between nodes

The most important idea in n8n, and the one people skip most often, is a single word: item. Once items make sense, so do "why does my workflow run once instead of five times", "why did the Slack node send 100 messages" and "why does my expression show undefined". This chapter settles all of it, and every later chapter comes back to it.

Why you have to understand items

After you finish the "push the calendar to Slack every morning" workflow in Chapter 8, you probably ran into a few odd things:

  • The Google Calendar node runs once and reads back five events, and the Slack node then sends five messages on its own — and nobody wrote a for-loop, did they?
  • In the Expression panel {{ $json.summary }} clearly has a value, but switch it to {{ $json.items[0].summary }} and you get undefined.
  • Google Sheet reads back an empty table and every downstream node is skipped outright — no error is raised, it simply does not run.
  • You add one field with a Set node and the output panel shows five rows, not the single row you expected.

All of these come from the same thing: what travels between one n8n node and the next is not a blob of JSON, it is a list of items, one row at a time. Zapier hides this; n8n lays items out in front of you — which is exactly why it can do more than Zapier, and why it is harder for a beginner than Zapier.

Chapter goal: by the end you will know what an item is, how many items a node takes in, how many times the next node runs, what an expression actually reads, and the right way to debug from the output panel. There is no new workflow to build here, but it helps a lot to open the Chapter 8 workflow and follow along.

An item is one record, like a row in Excel

The most useful analogy: every node's output is one Excel spreadsheet, and each row in that sheet is one item.

Excel termn8n termWhat it looks like
The whole sheetThe node's output (one array)[ {...}, {...}, {...} ]
One rowOne item{ name: "Elmo", age: 30 }
One columnOne field inside an itemname, age
One cellOne field's value on one item"Elmo"

Then the rule that matters most: the next node runs once for every single item. So Google Sheet reads back 100 rows → the Slack node sends 100 messages. That is not a bug, it is n8n's core behavior; the official docs call it item-based execution.

Tip: Write "item = one Excel row" on a sticky note and put it on your monitor. Every time a workflow behaves strangely, ask yourself first "how many items does this node get as input?" — eight times out of ten that finds the problem.

The compartments inside an item

An item is not plain JSON; it is an object with a few fixed compartments. You will only use the first one 99% of the time, but knowing the other two exist saves you trouble later.

CompartmentWhat goes in itWhen you need it
jsonThe main data, a plain JSON object. This is where you read 99% of the time.Almost every workflow.
binaryAttached file content (PDFs, images, CSVs and other binary data).Gmail attachments, Google Drive downloads, files an API returns.
pairedItemRecords which upstream item this item came from, so the Merge node can line them up.When you merge branches with the Merge node. n8n fills it in for you in most cases.

In code, a complete item looks like this:

{
  "json": {
    "name": "Elmo",
    "age": 30,
    "email": "[email protected]"
  },
  "binary": {
    "attachment": {
      "mimeType": "application/pdf",
      "fileName": "invoice.pdf",
      "data": "..."
    }
  },
  "pairedItem": { "item": 0 }
}

So when the next node wants the name field, the path is $json.name — note that it is $json.name, not $json.json.name: n8n strips that outer json layer for you, to keep expressions short.

Four core ways to pull data in an expression

Once you switch a node field into Expression mode (the gear or the = marker at the top right of the field), you are in expression territory. Only these four forms are worth memorizing for reading item data; everything else is a variation on them:

How to write itWhat it meansWhen to use it
{{ $json }}The whole JSON of the current item.When you want to see the whole thing, or pass the whole thing downstream.
{{ $json.field }}One field of the current item.The most common one. For example {{ $json.summary }}, {{ $json.email }}.
{{ $json['field with space'] }}Field names with a space, or with Chinese characters, need bracket notation.When the API returns fields named User Name, Order ID.
{{ $('Google Sheets').item.json.field }}Read data from a named upstream node (not just the previous one).Reaching past the nodes in between for data from two or three stops back.

$('Node Name') means "find that upstream node's output by its name". The node name is the one you see on the canvas (double-click a node to rename it). The advantage of writing it this way is that even with a pile of Set / IF nodes in between, you can still reach straight back for the original data.

Concept: you do not have to memorize the syntax when writing expressions. Click a field into Expression mode and an input panel slides out on the right; its left half lists the data from every upstream node (in Table / JSON / Schema views), and whichever field you click, it inserts the correct expression for you. Chapter 14 takes that panel apart in full.

How many times does one node run? Two modes

How many times a node runs is decided by two things: how many items the input has and the node's Execute Once setting. Most built-in nodes default to "as many runs as there are input items", but you can change that.

ModeBehaviorWhich nodes behave this way
Once for each item (the default)N items in the input → the node runs N times → the output is usually N items too.Most integration nodes (Slack, Gmail, HTTP Request calling an API and so on).
All items in one passN items in the input → the node runs once and gets the whole array → you decide inside how many items come out.Set, Aggregate, Item Lists, Code node (switchable), Sub-workflow (switchable).

To see or change which one a node uses: click the node to open its settings → switch to the Settings tab at the top → find the Execute Once toggle. Turn it on and the node runs once using only the first item, however many items the input has; the rest are dropped.

Warning: Execute Once means "run once with the first item", not "bundle every item together and run once". Plenty of people mix the two up. If you really want to fold 5 items into 1, what you need is the Aggregate or Item Lists node (Chapter 16 covers it in detail).

Data flowing through three nodes, step by step

Dizzy from the abstractions? Walk through the simplest 3-node workflow once and it clicks: Manual Trigger → Google Sheets (Read) → Slack (Send). Assume the Google Sheet holds 5 rows of contacts.

StageNodeInput itemsWhat it doesOutput items
StartManual Trigger— (no input)You press Execute by hand.1 empty item: [ {} ]
MiddleGoogle Sheets (Read Rows)1 itemRuns once for that 1 item, and reads 5 rows back from the sheet.5 items: [{row1}, {row2}, ...]
EndSlack (Send Message)5 itemsOne send per item → 5 messages go out.5 items (the result of each send)

See the point? The item count is multiplied by the node in the middle. Manual Trigger pushes in 1 empty item, Google Sheets expands it into 5 items, and Slack is run 5 times in a row automatically. There is not one line of for-loop code in the whole thing; the item model does the expanding.

AI×Odoo stage1 workflow: data flowing through 14 chained nodes, showing items expanded, filtered and aggregated along the way
Figure 9-1 A real 14-node workflow: data comes in from the Trigger on the left and is read, filtered, classified by AI and written back to Odoo — every line carries an array of items.
Tip: Most Trigger nodes (Manual, Schedule) emit only 1 item when they first fire. What actually multiplies the data is the reading node that comes after (Google Sheets Read, Gmail Trigger fetching new mail, a database SELECT). So when you check whether a workflow's item count is right, look at which node is the data source, not at the Trigger.

Three views for reading items in the output panel

After you press Execute step on a node (running that node on its own), or after the whole workflow finishes, the output panel on the right shows the items that node produced. Three view modes at the top let you switch between them, and each has its moment:

ViewWhat it looks likeWhen to use it
Table (a grid)An Excel-style grid: fields are columns, items are rows.A quick look at each item's values, and a check that the item count is right. This is the default view.
JSONThe raw JSON array, with objects you can expand / collapse.When Table cannot fit it (too many fields / a nested structure), or when you want to copy the whole thing somewhere else.
SchemaA tree of the field structure: field names and types only, no values.Look here before you write an expression — it tells you which fields exist and how to write the path.

The top of the panel also shows the "N items" count — the number you will look at most while debugging. If it is not what you expected, something went wrong at that node, so trace upstream.

In the Table view the small number in front of each row (0, 1, 2...) is the item index. To read a field on the first item you write $json.field (the item of the current iteration), not $json[0].field — one of the most common beginner mistakes.

Concept: the Schema view is badly underrated in n8n. Switch to it for a moment before writing an expression and you save nine tenths of the time otherwise spent typing away only to find the field name was wrong. Clicking a field in Schema also inserts the expression into the field you are editing.

Why does my workflow run once instead of five times?

This is the question beginners ask most in their first week. The cause is always one of three, and you can pin it down by reading the item count node by node in Executions:

CauseSymptomHow to confirm
A: the Trigger emits only 1 itemSchedule Trigger and Manual Trigger send exactly 1 empty item on every fire, by default. Expecting them to "run 5 times by themselves" is a misreading.Read the item count in the Trigger node's output panel.
B: some node has Execute Once turned onThere are 5 items upstream but this node runs once and stops — most likely you or someone else switched on Settings → Execute Once by accident.Read the output item count node by node, and find the one where 5 becomes 1.
C: the expression reads the wrong levelYou think $json.items expands the items, but it only reads the field named items inside the current item — and that field is an array, not n8n's idea of items.Use the Schema view on that node's output to tell whether items means several real items or one item containing an array called items.

C is a nasty one: "n8n items" and "a JSON field that happens to be called items" are two different things. APIs very often return something like this:

{
  "total": 5,
  "items": [
    { "id": 1, "name": "A" },
    { "id": 2, "name": "B" },
    ...
  ]
}

n8n treats the whole thing as one item (because the API returned one blob). To expand the items array into 5 n8n items, use the Split Out node (Chapter 16) and point it at the items field. Only after that do you have 5 items, and only then does the downstream node run 5 times in a row.

When binary data comes up

Most business workflows never touch binary at all. Only nodes that deal with the file itself produce binary data:

  • Gmail Trigger picks up a mail with attachments → they land in binary.attachment_0, binary.attachment_1...
  • Google Drive Download → the file content is in binary.data.
  • HTTP Request gets a PDF / image response and Response Format is set to File → binary.
  • Read/Write Binary File (only meaningful when you self-host).

To look at binary, switch to the Binary tab in the output panel (a fourth tab alongside Table / JSON / Schema, which only appears when there is binary). It lists each binary's mime type, file name and size, and images even get a preview.

Warning: binary sits in memory and travels with the whole execution: one 10MB attachment × 100 items is 1GB. Two rules for workflows with large files: (1) finish with it and drop it as early as you can — use a Set node to keep $json only and clear $binary; (2) avoid unnecessary Execute Workflow hand-offs (a sub-workflow copies it).

Common pitfalls

  1. An expression shows undefined

    Two possibilities: (1) the field name is wrong — switch to the Schema view and read the real field name (case, spaces, whether there is a data. prefix). (2) the upstream node never ran successfully — its output panel is empty or red. Fix the upstream node first, then worry about the expression.

  2. A node runs 100 times when you only wanted 1

    That is because there are 100 items upstream. Pick one of three approaches: (a) drop an Aggregate node in between to fold the 100 into 1; (b) use a Code node (Chapter 20) with return [ { json: { all: $input.all() } } ]; (c) if you only want the first record, turn on Execute Once in that node's Settings — but remember that means "take the first one", not "combine them all".

  3. The Merge node's item count does not add up

    Merge has four modes, and the wrong one changes the result completely: Append (end to end, A's 3 + B's 2 = 5), Combine (which then splits into three sub-options: Matching Fields compares field values like a SQL join, Position pairs up the same index, All Possible Combinations is a Cartesian product, A's 3 × B's 2 = 6), SQL Query (1.49.0+, write the SQL yourself), Choose Branch (emit the data from one side only). Older docs call All Possible Combinations Multiplex; the newer name replaced it, so do not panic when someone else's workflow still uses the old one. Decide which one you want before you use it; Chapter 16 goes into more detail.

  4. A node gets 0 items and is skipped

    That is how n8n behaves: when the input is an empty array, the node does not run. It is deliberate (you never have to write an empty check), but beginners read it as a broken node. Trace upstream to find who emitted 0 — usually (a) neither IF branch passed, (b) Google Sheet Read found no data, (c) a filter node filtered everything out.

  5. The item count is wrong after a Set node

    The Set node runs once for each item by default (the item count stays the same), and that is correct. If you see 5 in and 5 out but the fields have gone missing, the Set node's mode is usually on Keep Only Set, which wipes out the original fields — try Include All Fields or Include Selected Fields instead. Chapter 18 takes the Set node apart in full.

  6. The expression preview does not match what actually runs

    The expression editor previews against the upstream node's output from its last run — if the upstream node has not run yet, or ran wrong, the preview shows a stale value. The fix: press Execute step on the upstream node to make it produce fresh output, then come back and look at the expression preview again.

FAQ

Does Zapier have this item idea too?
It does, but Zapier hides it — by default every Zap fires on one record, and handling several means adding a Sub-Zap or Looping by Zapier. n8n chose to lay items out in front of you. The upside is the flexibility (the same workflow handles 1 record or 1000); the price is the extra 30 minutes a beginner spends on this chapter. Once it clicks, you will find Zapier's black box gets in your way instead.
How many items can it take at once? Is there a ceiling?
There is no hard limit technically, but there is one in practice: n8n keeps a whole execution's items in memory. A few thousand plain-JSON records are fine, tens of thousands get slow, and one or two hundred carrying binary can blow it up. For genuinely large volumes, batch the work with the Split In Batches node (Chapter 16), or do the data processing in the database layer and let n8n touch only the result.
Does binary data take up memory?
It does, and it is greedy. A 10MB PDF attachment sits whole in the execution's memory, and if it then triggers a sub-workflow it gets copied as well. The rules: (1) use a Set node to clear binary from items that do not need it; (2) the Cloud edition has an execution size limit, and going over it fails; (3) when you self-host, remember to watch the n8n container's memory usage.
How do I see how long the workflow actually ran, and how long each node took?
Every record on the Executions page in the sidebar carries a total duration. Open one and you can see how long each node took on its own (the small clock marker at the node's top right). The slow nodes are usually the ones calling outside APIs (Slack, the Google family, HTTP Request), not n8n itself. Chapter 17 on error handling covers how to set timeouts and retries.
Can I run the workflow on only some of the items instead of all of them?
You can. Put an IF or Filter node in between to filter on a condition: only the items that match carry on, the rest are stopped. Or use Split In Batches to work through them in batches (say 10 at a time, 10 rounds). Chapter 16 covers all of this in detail.
What is the difference between $json and $input.all()?
In an Expression field on an ordinary node, $json is the json of the item in the current iteration — because the node runs N times in a row, each pass points $json at a different item. $input.all() gives you the array of all the items this one node received (it returns an Array whose members are complete items, with .json / .binary). Expressions can call it too, but in practice you use it most in the Code node (Chapter 20), because a Code node is usually set to handle everything in one pass. Its siblings: $input.first(), $input.last(), $input.item.