Gateways
Gateways control how tokens split and merge in a process. Each gateway type has its own rules for which outgoing flows fire (split) and what it takes to advance (join).
Common attributes
| Attribute | Notes |
|---|---|
id | Required |
name | Optional |
default | Flow ID — fallback flow taken when no condition matches (exclusive and inclusive only) |
gatewayDirection | Informational; not enforced |
A default flow must be one of the gateway's outgoing flows and must not carry a conditionExpression.
Exclusive gateway (XOR)
Picks exactly one outgoing flow at a split. The first flow whose condition evaluates to true is taken; all others receive a "dead" token (the path is skipped). When used as a join, it's a pass-through merge — no synchronisation.
Behavior
| Scenario | Behavior |
|---|---|
| Split with conditions | Flows are evaluated in document order; first true wins |
Split with no match and a default | Default flow is taken |
Split with no match and no default | Runtime error |
| Join | Pass-through — every incoming token advances |
Example
<bpmn:exclusiveGateway id="gw-route" name="Route?" default="flow-default">
<bpmn:incoming>f1</bpmn:incoming>
<bpmn:outgoing>flow-vip</bpmn:outgoing>
<bpmn:outgoing>flow-default</bpmn:outgoing>
</bpmn:exclusiveGateway>
<bpmn:sequenceFlow id="flow-vip" name="VIP" sourceRef="gw-route" targetRef="task-vip">
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">=tier = "vip"</bpmn:conditionExpression>
</bpmn:sequenceFlow>
<bpmn:sequenceFlow id="flow-default" name="Standard" sourceRef="gw-route" targetRef="task-standard" />
Validation
| Check | Severity |
|---|---|
default doesn't match an outgoing flow | Error |
Default flow carries a conditionExpression | Error |
Non-default outgoing flow has no condition (when default is set) | Warning |
| Single outgoing flow has no condition and no default | Warning |
Parallel gateway (AND)
Splits into all outgoing flows simultaneously and joins by waiting for a token on every incoming flow.
Behavior
| Scenario | Behavior |
|---|---|
| Split | All outgoing flows are activated. No condition evaluation |
| Join | Waits until a live token has arrived on every incoming flow, then activates a single outgoing token |
Conditions on outgoing flows are ignored (with a warning at deployment).
Example
<bpmn:parallelGateway id="fork" name="Split">
<bpmn:incoming>f1</bpmn:incoming>
<bpmn:outgoing>f2</bpmn:outgoing>
<bpmn:outgoing>f3</bpmn:outgoing>
</bpmn:parallelGateway>
<!-- ... tasks in parallel branches ... -->
<bpmn:parallelGateway id="join" name="Join">
<bpmn:incoming>f2-done</bpmn:incoming>
<bpmn:incoming>f3-done</bpmn:incoming>
<bpmn:outgoing>f4</bpmn:outgoing>
</bpmn:parallelGateway>
Validation
| Check | Severity |
|---|---|
Outgoing flow carries a conditionExpression | Warning (condition is ignored) |
Inclusive gateway (OR)
Activates every outgoing flow whose condition evaluates to true. The matching join waits for all of those branches to arrive.
Behavior
| Scenario | Behavior |
|---|---|
| Split | All matching conditions activate their flows in parallel; if none match and a default is set, only the default fires; if none match and no default, runtime error |
| Join | Waits for every branch the matching split activated; merges branch variables into the parent scope before advancing |
Example
<bpmn:inclusiveGateway id="gw-or" name="Select Channels" default="flow-email">
<bpmn:incoming>f1</bpmn:incoming>
<bpmn:outgoing>flow-sms</bpmn:outgoing>
<bpmn:outgoing>flow-push</bpmn:outgoing>
<bpmn:outgoing>flow-email</bpmn:outgoing>
</bpmn:inclusiveGateway>
<bpmn:sequenceFlow id="flow-sms" sourceRef="gw-or" targetRef="send-sms">
<bpmn:conditionExpression>=smsEnabled</bpmn:conditionExpression>
</bpmn:sequenceFlow>
<bpmn:sequenceFlow id="flow-push" sourceRef="gw-or" targetRef="send-push">
<bpmn:conditionExpression>=pushEnabled</bpmn:conditionExpression>
</bpmn:sequenceFlow>
<bpmn:sequenceFlow id="flow-email" sourceRef="gw-or" targetRef="send-email" />
Validation
| Check | Severity |
|---|---|
default doesn't match an outgoing flow | Error |
Default flow carries a conditionExpression | Error |
Non-default outgoing flow has no condition (when default is set) | Warning |
Event-based gateway
Waits for the first of several events to fire and then takes the corresponding branch. Each outgoing flow must lead directly to an intermediate catch event (message, timer, or signal).
Attributes
| Attribute | Default | Notes |
|---|---|---|
instantiate | false | When true, this gateway can start a new process instance on the first event |
eventGatewayType | Exclusive | Exclusive = first event wins (the rest are cancelled); Parallel = every event that fires within the race window advances its branch |
Behavior
| Scenario | Behavior |
|---|---|
| Exclusive (default) | Races all outgoing catch events; the first to fire wins. The losing branches are cancelled |
| Parallel | All events that fire within the race window advance their branches |
| No event fires | Token waits indefinitely |
Example
<bpmn:eventBasedGateway id="gw-event" name="Wait for First">
<bpmn:incoming>f1</bpmn:incoming>
<bpmn:outgoing>flow-timer</bpmn:outgoing>
<bpmn:outgoing>flow-msg</bpmn:outgoing>
</bpmn:eventBasedGateway>
<bpmn:sequenceFlow id="flow-timer" sourceRef="gw-event" targetRef="catch-timer" />
<bpmn:intermediateCatchEvent id="catch-timer" name="30s Timeout">
<bpmn:incoming>flow-timer</bpmn:incoming>
<bpmn:outgoing>f-timeout</bpmn:outgoing>
<bpmn:timerEventDefinition>
<bpmn:timeDuration xsi:type="bpmn:tFormalExpression">PT30S</bpmn:timeDuration>
</bpmn:timerEventDefinition>
</bpmn:intermediateCatchEvent>
<bpmn:sequenceFlow id="flow-msg" sourceRef="gw-event" targetRef="catch-msg" />
<bpmn:intermediateCatchEvent id="catch-msg" name="Confirmation Received">
<bpmn:incoming>flow-msg</bpmn:incoming>
<bpmn:outgoing>f-confirmed</bpmn:outgoing>
<bpmn:messageEventDefinition messageRef="Msg_Confirm" />
</bpmn:intermediateCatchEvent>
Validation
| Check | Severity |
|---|---|
| Fewer than 2 outgoing flows | Error |
| Outgoing flow leads to a node that isn't an intermediate catch event | Error |
Outgoing flow carries a conditionExpression | Error |