Loops, Sub-workflows and End Steps
Three Flow steps shape a run as a whole. For each repeats a path for every matching row, Sub-workflow hands part of the work to another workflow, and End finishes the run with a result and a message. Together they let one workflow work through many records and keep large processes in readable pieces.
Where to find it
Architect Panel → Automation:
- Workflow Builder — For each, Sub-workflow and End are in the Flow group of the Steps palette
- Workflow Run History — parent and child runs are linked from each other
For each
- Add a For each step and choose Child records in: the datastore holding the rows.
- Choose Linked by field: the field on those rows that holds this record's ID (an order's lines, say). Leave it empty to take every row matching the rules, which is how a scheduled workflow works through records.
- Optionally add rules under Only rows where. Values may use placeholders, such as due date is less than {{today}}.
- Set At most this many rows (500 when blank, 5,000 at most).
- Optionally rename Call each row (default "item").
- Draw the Each row path: the steps that run for every row. Connect When done to what happens after the last row.
On the Each row path the current row is {{item.field}}. When a pass reaches the end of the path, or comes back into the For each step, the next row is taken. Steps such as Update record can act on "The current row of" the loop.
A run may take 1,000 steps; each row a For each works through raises that by 50, up to a ceiling of 100,000. Work much larger than that belongs in a scheduled workflow that starts one run per record.
Sub-workflow
- Build and publish the workflow to be called first. It must be active.
- Add a Sub-workflow step and choose Workflow to run. Workflows that are not active are marked in the list.
- Set On record: "current" for this record, or a placeholder holding the ID of a record of the other workflow's datastore, such as {{found.ID}} or {{item.ID}}.
- Tick Wait for it to finish before carrying on if this run should wait. It then fails if the child fails.
In Workflow Run History the child run shows Started by with a link to the parent, and the parent lists its Child runs. A workflow cannot call itself, and runs can nest at most five deep in one go.
Templates that bundle a sub-workflow (Month-end close, New customer onboarding) create it alongside the main workflow; publish it too.
End
- Finish the run as: Done or Failed.
- Message: recorded against the run; it may use placeholders.
End stops the whole run there, including every open parallel branch and loop. In a workflow that runs before a record is saved, ending as Failed refuses the save and the message is what the person saving sees. A run that simply runs out of steps also finishes as Done; an End step lets you say why.
What goes wrong
- "Connect the 'each' path - it is what runs for every row." The For each step has nothing to repeat.
- "Step budget exhausted": the When done path leads back into the For each, or a loop has no exit.
- "The chosen sub-workflow no longer exists." It was deleted; choose another.
- A parent run waits for ever. The child is waiting too (for an approval, say). Open the child from Child runs to see what it waits for.
- The For each did nothing. No rows matched, or the link field is wrong; Simulate shows which steps ran on the Each row path.
Worked example
A wholesaler checks stock every morning. A scheduled workflow uses For each over active items with a reorder point, at most 500. On the Each row path, Set variables and two library functions work out stock on hand and a reorder quantity, and a Condition asks whether the item is at or below its reorder point; Yes raises a requisition. When done goes to End, Done, with the message "All items checked". The Stock reorder template builds exactly this.
Recommendations
- Always set At most this many rows to a number you expect.
- Prefer one run per record for scheduled work that waits or asks people.
- Publish sub-workflows before their parent.
- End rejected and failed paths with a message so the run history explains itself.