Skip to main content

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...UseWhy
Take one of several paths based on true/false conditionsBranchEach condition gets its own output path; conditions can be combined with AND/OR.
Route on a single value (status, type, country code)SwitchOne selector, one matching case. Cleaner than many Branch conditions.
Repeat work N times, until done, or per array itemLoopThree loop modes cover counts, exit conditions, and iteration.
Run independent paths at once and combine resultsParallelConcurrent 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.

  1. 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.

  2. 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:

    OperatorNeeds a value?
    EqualsYes
    Not EqualsYes
    ContainsYes
    Not ContainsYes
    Greater ThanYes
    Less ThanYes
    ExistsNo
    Not ExistsNo

    Exists and Not Exists ignore the value box. Every other operator needs a non-empty value.

  3. Combine conditions with AND or OR

    Set the logical operator between conditions to AND or OR. 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.

  4. 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.

Branch operators are a fixed list, not freehand JSONata

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.

  1. Set the selector

    Enter a selector, a JSONata expression that produces the value you want to route on, for example $trigger.status or $steps.classify.data.category. The selector cannot be empty and must be valid JSONata.

  2. 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.

  3. Choose a match mode

    The match mode controls how the selector value is compared to each case value. The default is Strict.

    Match modeValueBehavior
    StrictstrictExact match with type coercion for common cases (for example, "123" = 123).
    LooselooseAttempts type coercion before comparison.
    RegexregexCase values are treated as regex patterns (strings only).
    ContainscontainsChecks if the selector value contains the case value (strings/arrays).
  4. Choose no-match behavior

    Decide what happens when nothing matches. The default is Default.

    No-match behaviorValueResult
    DefaultdefaultTake the default path if configured, otherwise complete the workflow.
    ErrorerrorReturn an error if no case matches and no default path exists.
    SkipskipSkip execution and complete the workflow gracefully.

    If you set a default path, connect its handle to a downstream step.

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.

  1. Pick a loop type

    Choose how the loop decides when to stop:

    Loop typeValueWhat it needs
    Fixed CountcountRuns a fixed number of times.
    Condition-basedconditionA non-empty exit condition expression; repeats until the condition is met.
    Array IterationarrayA non-empty arrayPath, a dot-notation path to the array, for example data.items.
  2. 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.

  3. 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.

  4. 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 policyBehavior
    Continue on errorCollect failures and still succeed (default).
    Collect errorsSucceed if all items pass, fail otherwise.
    Fail fastCancel remaining iterations on the first failure.
$currentItem and $currentIndex only resolve inside the loop body

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.

  1. Define branches

    A Parallel node ships with two branches ("Branch 1", "Branch 2") and requires at least 2. Each branchId must be unique and non-empty. Connect each branch to the path it should run.

  2. Choose a completion mode

    The completion mode sets when the block is considered done. The default is all.

    Completion modeValueBehavior
    AllallWait for every branch. Cancel on a non-skippable failure.
    RaceraceFirst successful branch wins, remaining branches cancel. Requires at least 2 branches.
    SettledsettledWait for all branches regardless of failures.
    IndependentindependentFire and forget. Branches run with no barrier.
  3. 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 not independent.

    Merge strategyValueResult
    ArrayarrayEach successful branch's output, keyed by branchId.
    FirstfirstThe output of the first successful branch in definition order.
    MergemergeSuccessful branch outputs shallow-merged into one object.
  4. Set per-branch and group limits (optional)

    Tune these when you need them; all default to "off":

    • skipFailure (per branch, default false): when true, that branch failing does not fail the block.
    • branchTimeoutMs (per branch, default 0 = no timeout) and groupTimeoutMs (whole block, default 0 = 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.

After the join, downstream steps receive a structured output:

  • results is an array of branch results, ordered by branch definition (not completion order).
  • mergedData holds the successful branches' data, keyed by branchId.
  • summary reports counts (succeeded, failed, cancelled, timedOut, total) and a releaseReason of all_completed, failure_threshold, race_winner, or timeout.

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.

MessageNodeFix
Branch node must have at least 2 conditionsBranchAdd conditions until you have at least 2 (max 8).
Branch node has too many conditions (maximum 8)BranchRemove conditions to get back to 8 or fewer.
Switch node must have a selector expressionSwitchEnter a non-empty selector.
Invalid selector expressionSwitchFix the JSONata so the selector compiles.
Switch node must have at least one caseSwitchAdd at least one case.
Duplicate pathId "<id>" found in casesSwitchGive each case a unique path ID.
maxIterations is requiredLoopSet Maximum Iterations (1 to 1000).
maxIterations cannot exceed 1000LoopLower the cap to 1000 or less.
Array path is required for array-type loopsLoopSet arrayPath (for example data.items).
Condition expression is required for condition-type loopsLoopEnter the exit condition expression.
Loop node has no incoming edges and will never be executedLoopConnect an upstream step into the Loop.
Parallel node must have at least 2 branchesParallelKeep at least 2 branches.
Duplicate branchId "<id>" foundParallelMake each branchId unique.
Each branch must have a non-empty branchIdParallelGive every branch an ID.

A common case worth calling out: when you add a Branch or Switch case but forget to connect its handle, the publish gate fails with "Branch node condition <n> (handle: condition-<i>) has no connected edge" or "Switch node case <label> (pathId: <id>) has no connected edge". Connect every condition and case to a downstream step, including the default path if you configured one. The same applies to a Loop: connect both the continue and exit handles. For the complete publish-gate reference, see Fix publish errors.

Was this helpful?