Skip to main content

Sequence Flow

Sequence flows connect flow nodes — events, tasks, gateways, and sub-processes — and determine which token paths are taken at execution time.

Attributes

AttributeRequiredNotes
idyesUnique flow identifier
namenoDisplay label
sourceRefyesID of the source node
targetRefyesID of the target node

Conditions

A <conditionExpression> child carries a FEEL expression evaluated when the token leaves a node with multiple outgoing flows. The flow is taken if the expression returns true.

<bpmn:sequenceFlow id="f1" sourceRef="svc1" targetRef="task-success">
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">=price &gt; 0</bpmn:conditionExpression>
</bpmn:sequenceFlow>

Condition expressions can sit on flows leaving:

  • Exclusive (XOR) gateways — exactly one matching flow is taken; ties resolve in document order.
  • Inclusive (OR) gateways — every matching flow is taken in parallel.
  • Activities — every matching flow is taken in parallel (uncontrolled fork, BPMN 2.0 §13.2.1).

A flow leaving a node that has only one outgoing flow ignores any condition and is always taken.

Default flows

A node with multiple outgoing flows can declare one of them as the default via the default="<flowId>" attribute. The default flow fires when every other outgoing flow's condition evaluates to false. The engine recognises default on:

  • exclusive (XOR) gateways
  • inclusive (OR) gateways
  • tasks (service / user / script / business-rule / send / receive / manual / generic)
  • sub-processes (embedded and ad-hoc)
  • call activities

A default flow must not carry a <conditionExpression> of its own — its only job is to be the fallback when nothing else matches.

<!-- XOR gateway with a default -->
<bpmn:exclusiveGateway id="gw1" default="f-fallback">
<bpmn:outgoing>f-vip</bpmn:outgoing>
<bpmn:outgoing>f-fallback</bpmn:outgoing>
</bpmn:exclusiveGateway>

<bpmn:sequenceFlow id="f-vip" sourceRef="gw1" targetRef="task-vip">
<bpmn:conditionExpression>=tier = "vip"</bpmn:conditionExpression>
</bpmn:sequenceFlow>
<bpmn:sequenceFlow id="f-fallback" sourceRef="gw1" targetRef="task-default" />
<!-- Service task with a default — same shape, no extra gateway -->
<bpmn:serviceTask id="route" default="f-default">
<bpmn:extensionElements>
<zeebe:taskDefinition type="route-task" />
</bpmn:extensionElements>
<bpmn:outgoing>f-route-vip</bpmn:outgoing>
<bpmn:outgoing>f-default</bpmn:outgoing>
</bpmn:serviceTask>

How outgoing flows are selected

When a token leaves a node with multiple outgoing flows, the engine evaluates them in two passes:

  1. Non-default flows. Each outgoing flow whose condition evaluates to true emits a token. A flow without a <conditionExpression> is treated as always-true. The default flow (if any) is skipped in this pass.
  2. Default fallback. If pass 1 emitted zero tokens and the node declares a default flow, the default emits a token.

Behaviour at a glance:

Source node kindMultiple non-default flows matchNo non-default flows matchNo conditional flows; only an unconditional default
Exclusive gateway (XOR)Take the first match in document order; rest droppedTake the default if declared; otherwise raise GatewayNoMatchErrorTake the default
Inclusive gateway (OR)Take every match in parallelTake the default if declared; otherwise raise GatewayNoMatchErrorTake the default
ActivityEmit a token on every match (uncontrolled fork)Emit on the default if declared; otherwise the token simply has no successor and the activity's branch terminatesEmit on the default
Parallel gateway (AND)Always emits on every outgoing flow; conditions are ignored (warning at validation time)n/an/a

Three-way example

Consider a service task with three outgoing flows:

  • f-cond — condition =x > 0, target task-positive.
  • f-uncond — no condition, target task-always.
  • f-default — declared as default, target task-fallback.
<bpmn:serviceTask id="route" default="f-default">
<bpmn:extensionElements>
<zeebe:taskDefinition type="route-task" />
</bpmn:extensionElements>
<bpmn:outgoing>f-cond</bpmn:outgoing>
<bpmn:outgoing>f-uncond</bpmn:outgoing>
<bpmn:outgoing>f-default</bpmn:outgoing>
</bpmn:serviceTask>

<bpmn:sequenceFlow id="f-cond" sourceRef="route" targetRef="task-positive">
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">=x &gt; 0</bpmn:conditionExpression>
</bpmn:sequenceFlow>
<bpmn:sequenceFlow id="f-uncond" sourceRef="route" targetRef="task-always" />
<bpmn:sequenceFlow id="f-default" sourceRef="route" targetRef="task-fallback" />

Outcomes per x:

x valuef-cond (x > 0)f-uncond (no condition)f-default (default)Result
5true → emitsalways-true → emitsskippedTwo parallel tokens: task-positive and task-always
-1false → skippedalways-true → emitsskippedOne token: task-always
(impossible)false(cannot be false)would emitf-default never fires here

The default flow f-default in this model is dead code: as long as f-uncond has no condition, the non-default pass always emits at least one token, and the fallback pass never runs. The validator does not flag this — the same model with a different unconditional sibling (e.g. an event) is intentional in some patterns — but it is worth catching in review. To make the default reachable, give f-uncond a condition that can be false (e.g. =alwaysTrue and not panic), or remove it.

Gateway-only nuance: parallel and event-based

  • Parallel gateways (AND) ignore conditions on outgoing flows entirely. Every outgoing flow activates. A <conditionExpression> here is a modeling error and the validator emits a warning.
  • Event-based gateways route on whichever attached intermediate catch event fires first. Their outgoing flows must not carry conditions (validation error) and must each lead to an intermediateCatchEvent.

Validation

CheckSeverity
Default flow ID isn't one of the source node's outgoing flowsError
Default flow carries a conditionExpressionError
Outgoing flow on an exclusive gateway has no condition (and no default is set)Warning
Outgoing flow on a parallel gateway carries a conditionWarning (the condition is ignored)
Outgoing flow on an event-based gateway carries a conditionError
Outgoing flow on an event-based gateway leads to a non-catch-event targetError
Start event has any incoming sequence flowError
End event has any outgoing sequence flowError
Intermediate catch event does not have exactly one outgoing sequence flowError
Activity marked isForCompensation="true" has incoming flowsError

Examples

<!-- Unconditional flow -->
<bpmn:sequenceFlow id="f1" sourceRef="start" targetRef="task1" />

<!-- Conditional flow off a gateway -->
<bpmn:sequenceFlow id="f2" name="price > 0" sourceRef="gw1" targetRef="task2">
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">=price &gt; 0</bpmn:conditionExpression>
</bpmn:sequenceFlow>

<!-- Default flow off a gateway (no condition) -->
<bpmn:sequenceFlow id="f3" name="default" sourceRef="gw1" targetRef="task3" />
<!-- gw1 must declare default="f3" -->

<!-- Conditional + default off a service task -->
<bpmn:serviceTask id="route" default="route-fallback">
<bpmn:extensionElements><zeebe:taskDefinition type="route-task"/></bpmn:extensionElements>
<bpmn:outgoing>route-vip</bpmn:outgoing>
<bpmn:outgoing>route-fallback</bpmn:outgoing>
</bpmn:serviceTask>
<bpmn:sequenceFlow id="route-vip" sourceRef="route" targetRef="task-vip">
<bpmn:conditionExpression>=tier = "vip"</bpmn:conditionExpression>
</bpmn:sequenceFlow>
<bpmn:sequenceFlow id="route-fallback" sourceRef="route" targetRef="task-standard" />