- Documentation
- Workflows
- Workflow Nodes
- Route, repeat, and parallelize steps
Route, repeat, and parallelize steps
Configure Branch, Switch, Loop, and Parallel nodes to route work by condition, iterate over arrays, and run paths concurrently.
What these nodes do
Control-flow nodes decide which steps run, how many times, and in what order. You add them from the Add node panel under the System tab, in the Control Flow category.
- Branch sends a run down a different path depending on whether each condition is true.
- Switch evaluates one value and routes to the case that matches it.
- Loop repeats a path a fixed number of times, until a condition is met, or once per item in an array.
- Parallel runs two or more paths at the same time and merges their outputs.
This page covers configuring each node and merging branches back together. To write the expressions that conditions and selectors read, see Expressions.
When to use each node
| You want to... | Use | Why |
|---|---|---|
| Take one of several paths based on true/false conditions | Branch | Each condition gets its own output path; conditions can be combined with AND/OR. |
| Route on a single value (status, type, country code) | Switch | One selector, one matching case. Cleaner than many Branch conditions. |
| Repeat work N times, until done, or per array item | Loop | Three loop modes cover counts, exit conditions, and iteration. |
| Run independent paths at once and combine results | Parallel | Concurrent branches with a merge strategy at the join. |
Configure a Branch node
A Branch node holds a list of conditions. Each condition routes to its own output path. You can also add a default path for runs that match no condition.
Add the Branch node
Open Add node, switch to the System tab, and choose Branch from the Control Flow category. Connect your upstream step into it.
Write each condition
A condition has three parts: a field (a JSONata path into upstream data, such as
$trigger.order.total), an operator, and a value. Pick the operator from the fixed list:Operator Needs a value? Equals Yes Not Equals Yes Contains Yes Not Contains Yes Greater Than Yes Less Than Yes Exists No Not Exists No ExistsandNot Existsignore the value box. Every other operator needs a non-empty value.Combine conditions with AND or OR
Set the logical operator between conditions to
ANDorOR. A Branch node requires at least 2 conditions and allows at most 8. Connect each condition's output handle to the path that should run when it matches.Add a default path (optional)
If you want a fallback for runs that match no condition, connect the node's default path handle to a downstream step. It is fine to leave the default path unconnected: a run that matches no condition simply ends at the Branch. Publishing shows no warning for it. An assistant building the workflow for you sees a note about it when it validates the draft or previews the publish.
The field is a JSONata path, but the operator and value are structured inputs you pick and type in the condition builder. You do not write a raw boolean JSONata expression for a Branch condition.
Configure a Switch node
A Switch node evaluates one selector expression, then compares its result against each case's value and routes to the first match.
Set the selector
Enter a selector, a JSONata expression that produces the value you want to route on, for example
$trigger.statusor$steps.classify.data.output.label. The selector cannot be empty and must be valid JSONata.Add cases
Add at least one case. Each case has a value to match and a unique path ID; you can also give it a label and description. Connect every case to the step that should run when it matches.
Choose a match mode
The match mode controls how the selector value is compared to each case value. The default is Strict.
Match mode Value Behavior Strict strictExact match with type coercion for common cases (for example, "123"=123).Loose looseAttempts type coercion before comparison. Regex regexCase values are treated as regex patterns (strings only). Contains containsChecks if the selector value contains the case value (strings/arrays). Choose no-match behavior
Decide what happens when nothing matches. The default is Default.
No-match behavior Value Result Default defaultTake the default path if configured, otherwise complete the workflow. Error errorFail the step (code SWITCH_NO_MATCH) if no case matches and no default path is connected.Skip skipSkip execution and complete the workflow gracefully. If you set a default path, connect its handle to a downstream step. If no default path is connected and No match behavior is Default (or you configured a default path and left it unwired), publish and validation warn that runs end at this step without doing anything. Error mode fails the step instead, and Skip with no default path is an explicit choice, so neither warns.
Configure a Loop node
A Loop node repeats a path. It has two output handles: continue (the loop body that runs each pass) and exit (the path taken once looping finishes). Connect both, or the publish gate warns that one is unconnected.
Pick a loop type
Choose how the loop decides when to stop:
Loop type Value What it needs Fixed Count countRuns a fixed number of times. Condition-based conditionA non-empty exit conditionexpression; repeats until the condition is met.Array Iteration arrayA non-empty arrayPath, a dot-notation path to the array, for exampledata.items.Set the maximum iterations
Every loop requires Maximum Iterations. The range is 1 to 1000. A cap above 500 raises a warning because high caps increase execution time and cost.
Reference the current item inside an array loop
Inside the body of an Array Iteration loop, two bindings are available:
$currentItem(the current element) and$currentIndex(its zero-based position). Use them in any field inside the loop body, for example$currentItem.email.Choose an execution mode (array loops only)
Array loops run sequential by default. Switch to parallel to process items concurrently. Parallel mode is only valid for Array Iteration loops; sequential loops must not carry the parallel-only fields.
When you choose parallel, set:
- Max Concurrent Iterations (
maxConcurrency), range 1 to 50, default 10. - An error policy, one of:
Error policy Behavior Continue on error Collect failures and still succeed (default). Collect errors Succeed if all items pass, fail otherwise. Fail fast Cancel remaining iterations on the first failure. An empty array is not an error in either mode: the loop runs zero times and takes its exit path.
- Max Concurrent Iterations (
These bindings exist only inside an Array Iteration loop's body. Referencing them outside that
body fails with SCOPE_BINDING_OUT_OF_SCOPE: move the reference inside the loop, or remove it.
See Expressions for the full scope rules.
Configure a Parallel node and merge branches
A Parallel node runs two or more branches concurrently. Each branch is one outgoing path. Their outputs come back together at the join, where a merge strategy combines them.
A path inside a branch that ends, such as a handled error path with no next step or a Branch with no matching condition, ends that branch. The join still waits for the other branches, and the steps after it run.
Define branches
A Parallel node ships with two branches ("Branch 1", "Branch 2") and requires at least 2. Each
branchIdmust be unique and non-empty. Connect each branch to the path it should run.Choose a completion mode
The completion mode sets when the block is considered done. The default is
all.Completion mode Value Behavior All allWait for every branch. Cancel on a non-skippable failure. Race raceFirst successful branch wins, remaining branches cancel. Requires at least 2 branches. Settled settledWait for all branches regardless of failures. Independent independentFire and forget. Branches run with no barrier. Choose a merge strategy
The merge strategy decides how branch outputs combine at the join. The default is
array. This is only meaningful when the completion mode is notindependent.Merge strategy Value Result Array arrayEach successful branch's output, keyed by branchId.First firstThe output of the first successful branch in definition order. Merge mergeSuccessful branch outputs shallow-merged into one object. Set per-branch and group limits (optional)
Tune these when you need them; all default to "off":
- skipFailure (per branch, default
false, shown as Skip failure): only matters in All mode. When Enabled, the other branches keep running if this branch fails; when Disabled, this branch failing cancels the branches still running. - branchTimeoutMs (per branch, default
0= no timeout) and groupTimeoutMs (whole block, default0= no timeout). Both must be non-negative. - maxConcurrency (default
0= unlimited). A value larger than the branch count raises a warning. Must be non-negative.
- skipFailure (per branch, default
After the join, downstream steps receive a structured output:
resultsis an array of branch results, ordered by branch definition (not completion order).mergedDataholds the successful branches' data, keyed bybranchId.summaryreports counts (succeeded,failed,cancelled,timedOut,total) and areleaseReasonofall_completed,failure_threshold,race_winner, ortimeout.
Read these with $steps, for example $steps.parallel1.data.summary.succeeded or $steps.parallel1.data.mergedData.branch-0.
Verify your configuration
Each control-flow node has a test button in its configuration panel ("Test branch", "Test switch", "Test loop"). Testing runs the node for real against pinned upstream output, so route decisions reflect actual data.
The test button only fires once the node is valid. For example, an unconfigured Switch shows the tooltip "Configure a selector and at least one valid case before testing." Configure the node until the button enables, then run the test and confirm the run took the path you expected. See Test a node and publish for the full test-then-publish flow.
Troubleshooting
These messages come from the publish gate. A version cannot enter the live cohort until every one clears.
| Message | Node | Fix |
|---|---|---|
| Branch node must have at least 2 conditions | Branch | Add conditions until you have at least 2 (max 8). |
| Branch node has too many conditions (maximum 8) | Branch | Remove conditions to get back to 8 or fewer. |
| Switch node must have a selector expression | Switch | Enter a non-empty selector. |
| Invalid selector expression | Switch | Fix the JSONata so the selector compiles. |
| Switch node must have at least one case | Switch | Add at least one case. |
Duplicate pathId "<id>" found in cases | Switch | Give each case a unique path ID. |
| maxIterations is required | Loop | Set Maximum Iterations (1 to 1000). |
| maxIterations cannot exceed 1000 | Loop | Lower the cap to 1000 or less. |
| Array path is required for array-type loops | Loop | Set arrayPath (for example data.items). |
| Condition expression is required for condition-type loops | Loop | Enter the exit condition expression. |
| Loop node has no incoming edges and will never be executed | Loop | Connect an upstream step into the Loop. |
| Parallel node must have at least 2 branches | Parallel | Keep at least 2 branches. |
Duplicate branchId "<id>" found | Parallel | Make each branchId unique. |
| Each branch must have a non-empty branchId | Parallel | Give every branch an ID. |
A common case worth calling out: when you add a Branch condition or Switch case but forget to connect its handle, publish still succeeds, and the toast warns Branch "<step name>" condition <n> (handle: condition-<i>) has no following node — the run ends when this path is taken or Switch "<step name>" case "<label>" (pathId: <id>) has no following node — the run ends when this path is taken. A Switch in Default no-match mode with no connected default path warns that when no case matches, runs end at the step without doing anything. A Branch with no default path publishes without a warning, because ending the run when no condition matches is a normal way to build. Inside a Parallel branch or a parallel Loop item, an unmatched Branch ends only that branch or item, and the rest of the run carries on. Connect every condition and case you expect to continue to a downstream step, and connect a default path unless you want unmatched runs to end there. The same applies to a Loop: connect both the continue and exit handles. For the complete publish-gate reference, see Fix publish errors.
Related
- Expressions for the JSONata aliases conditions and selectors read.
- Test a node and publish for testing nodes and clearing the publish gate.
- Fix publish errors for the full list of validation messages.