Skip to main content

Loop

Iterates over a collection of items, executing the body branch once for each item.

Properties

PropertyRequiredDescription
ItemsYesThe array to iterate over. Accepts an in-memory array or a file reference from a Parse CSV or Transform node. Supports expressions

Output ports

PortWhen
bodyExecutes once per item
completedExecutes 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:

FieldTypeDescription
currentItemAnyThe value of the current item in the collection
indexNumberZero-based position of the current item
isFirstBooleantrue on the first iteration
isLastBooleantrue on the last iteration
totalCountNumberTotal 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.
  • currentItem is 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:

  1. Name the Loop node For Each User. Set Items to {{ $nodes['Get Users'].users }}.
  2. Connect the body port to an HTTP Request node.
  3. In the HTTP Request URL, use {{ $nodes['For Each User'].currentItem.id }}.
  4. 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.