Appearance
ForEach node
The ForEach node loops over an array. For each item it runs the sub-branch wired to its loop port, then — once every item is processed — continues on its next port. Use it to send an email to each recipient, insert each row, or transform every entry in a list.
Component id: flowrunner/foreach.
How it works
ForEach reads a collection reference, expects it to be an array, and iterates. On each pass it writes the current item into the item variable and walks the loop branch to completion before moving to the next item. When the array is exhausted it leaves on next.
The collection
The collection field is a dotted reference of the form namespace.field — for example start.recipients or response.body. The engine splits on the first dot: everything before it is the namespace, everything after is the field. It reads refs[namespace][field].
- If that value is an array, ForEach iterates it.
- If it's anything else (missing, a scalar, an object), ForEach treats it as an empty array — zero iterations — and continues straight to
next.
The item variable
Each iteration writes the current item under the itemVar name (default item):
- If the item is a plain object, it's stored as-is, so you read its fields with
item.name,item.email, and so on. - If the item is a scalar (string, number) or an array, it's wrapped as
{ value: <item>, index: <i> }— read the value withitem.valueand the position withitem.index.
Config
| Field | Required | Description |
|---|---|---|
collection | Yes | Dotted reference to the array to loop over (start.items). Read as refs[namespace][field]; non-arrays yield zero iterations. |
itemVar | No (default item) | The variable name each item is written to during its iteration. |
Ports
| Port | Followed when |
|---|---|
loop | Once per item — the sub-branch runs to completion for each element. |
next | After every item has been processed. |
WARNING
ForEach is capped at 10,000 iterations. An array longer than that fails the node (message: foreach: too many iterations) rather than running unbounded. If you have a wired error port, the failure routes there.
Example
Email every address submitted with the form:
text
Start (body: { recipients: [...] })
→ ForEach collection: start.recipients itemVar: person
loop → Email to: person.email subject: "Hello ${person.name}"
→ next → EndNOTE
Nodes inside the loop branch overwrite the same refs on every pass, so a value written during one iteration is replaced on the next. To accumulate results across iterations, write them to an external store (a MongoDB collection) inside the loop.