Loop
Iterates over a collection of items, executing the body branch once for each item.
Properties
| Property | Required | Description |
|---|---|---|
| Items | Yes | The array to iterate over. Accepts an in-memory array or a file reference from a Parse CSV or Transform node. Supports expressions |
Output ports
| Port | When |
|---|---|
body | Executes once per item |
completed | Executes once after all iterations have finished |
Connect your per-item logic to the body port. Connect any post-loop logic to the completed port.
Loop context
Inside the body branch, the current iteration is available via the loop node's own name:
| Field | Type | Description |
|---|---|---|
currentItem | Any | The value of the current item in the collection |
index | Number | Zero-based position of the current item |
isFirst | Boolean | true on the first iteration |
isLast | Boolean | true on the last iteration |
totalCount | Number | Total number of items |
{{ $nodes['My Loop'].currentItem }}
{{ $nodes['My Loop'].index }}
Replace My Loop with the actual name you gave the loop node. If the items are objects, navigate into them directly:
{{ $nodes['My Loop'].currentItem.email }}
Using the node name rather than a fixed key means nested loops each have their own independent context — inner loop body nodes reference the inner loop node, outer body nodes reference the outer loop node.
Large file iteration
When Items receives a JSONL file reference (produced by Parse CSV or Transform when processing large inputs), the Loop node switches to a streaming cursor mode:
- The file is downloaded once at the start of the loop and its lines are cached in memory for the duration of the run.
- Each iteration reads a single row from that cache — the full dataset is never loaded into the workflow engine's state.
currentItemis the deserialised object for that row, identical in shape to what you would get from an in-memory loop.
This allows loops over datasets with millions of rows without storing row data in workflow state or sending it across message queues. The workflow author does not need to configure anything differently — passing a file reference to Items is enough.
Example
Send a separate HTTP request for each user in a list:
- Name the Loop node
For Each User. Set Items to{{ $nodes['Get Users'].users }}. - Connect the body port to an HTTP Request node.
- In the HTTP Request URL, use
{{ $nodes['For Each User'].currentItem.id }}. - Connect the completed port to a Variable node to record that processing finished.
Notes
- If Items resolves to an empty array or an empty file, the body branch does not execute and the completed port fires immediately.
- If Items resolves to a non-array, non-file value the node fails. Use a Convert node upstream if the data arrives as a JSON string.
- Nodes in the body branch can themselves fail — configure error handling on those nodes individually.