Skip to content

BPMN Gateway

Process execution can be pictured as tokens moving through a process model. A token marks where a process instance currently is. Plain sequence flow just moves a token along. Gateways route tokens in more complex patterns, and parallel gateways create new tokens.

Exclusive gateway (XOR). As a split, it picks one outgoing flow based on data, such as process variables. One flow can have no condition. The gateway must then name it as the default flow. As a join, it only passes tokens through. It does not synchronize concurrent flows the way a parallel gateway does.

Parallel gateway (AND). As a split, it takes all outgoing flows. As a join, it waits until every incoming flow has been taken.

Inclusive gateway (OR). As a split, it takes every outgoing flow whose condition is fulfilled. The join is finished when all incoming flows were taken. It is also finished when no path remains from any active node to it.

Event-based gateway. It waits for events and follows the flow of the first one that is triggered. The other events are then no longer possible. In Camunda, each target must be an intermediate catch event of type timer, message, or signal.

An online shop receives an order. A parallel split starts “pack goods” and “prepare invoice” at the same time. A parallel join waits for both before the next step. Then an exclusive split checks payment data. Paid orders go on to shipping. Other orders take the default flow to a reminder step.

Each gateway type fits one routing intent: exactly one path, all paths, or the paths whose conditions hold. An exclusive join does not wait for concurrent branches. A parallel join waits for every incoming flow. Choose the join type to match the split that created the branches.

A parallel split and join, followed by an exclusive split with a default flow.

Diagram source
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" targetNamespace="http://example.com/gw">
<process id="order" isExecutable="false">
<startEvent id="start" name="Order received">
<outgoing>f1</outgoing>
</startEvent>
<parallelGateway id="split" name="Split">
<incoming>f1</incoming>
<outgoing>f2</outgoing>
<outgoing>f3</outgoing>
</parallelGateway>
<task id="pack" name="Pack goods">
<incoming>f2</incoming>
<outgoing>f4</outgoing>
</task>
<task id="invoice" name="Prepare invoice">
<incoming>f3</incoming>
<outgoing>f5</outgoing>
</task>
<parallelGateway id="join" name="Join">
<incoming>f4</incoming>
<incoming>f5</incoming>
<outgoing>f6</outgoing>
</parallelGateway>
<exclusiveGateway id="xor" name="Paid?" default="fDefault">
<incoming>f6</incoming>
<outgoing>fPaid</outgoing>
<outgoing>fDefault</outgoing>
</exclusiveGateway>
<task id="ship" name="Ship order">
<incoming>fPaid</incoming>
<outgoing>f7</outgoing>
</task>
<task id="remind" name="Send reminder">
<incoming>fDefault</incoming>
<outgoing>f8</outgoing>
</task>
<endEvent id="end" name="Done">
<incoming>f7</incoming>
<incoming>f8</incoming>
</endEvent>
<sequenceFlow id="f1" sourceRef="start" targetRef="split" />
<sequenceFlow id="f2" sourceRef="split" targetRef="pack" />
<sequenceFlow id="f3" sourceRef="split" targetRef="invoice" />
<sequenceFlow id="f4" sourceRef="pack" targetRef="join" />
<sequenceFlow id="f5" sourceRef="invoice" targetRef="join" />
<sequenceFlow id="f6" sourceRef="join" targetRef="xor" />
<sequenceFlow id="fPaid" name="paid" sourceRef="xor" targetRef="ship">
<conditionExpression>paid = true</conditionExpression>
</sequenceFlow>
<sequenceFlow id="fDefault" name="otherwise" sourceRef="xor" targetRef="remind" />
<sequenceFlow id="f7" sourceRef="ship" targetRef="end" />
<sequenceFlow id="f8" sourceRef="remind" targetRef="end" />
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_order">
<bpmndi:BPMNPlane id="BPMNPlane_order" bpmnElement="order">
<bpmndi:BPMNShape id="BPMNShape_start" bpmnElement="start">
<dc:Bounds x="80" y="102" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="68" y="143" width="60" height="28" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="BPMNShape_split" bpmnElement="split" isMarkerVisible="true">
<dc:Bounds x="216" y="95" width="50" height="50" />
<bpmndi:BPMNLabel>
<dc:Bounds x="221" y="76" width="41" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="BPMNShape_pack" bpmnElement="pack">
<dc:Bounds x="366" y="80" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="BPMNShape_invoice" bpmnElement="invoice">
<dc:Bounds x="366" y="240" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="BPMNShape_join" bpmnElement="join" isMarkerVisible="true">
<dc:Bounds x="566" y="95" width="50" height="50" />
<bpmndi:BPMNLabel>
<dc:Bounds x="574" y="76" width="34" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="BPMNShape_xor" bpmnElement="xor" isMarkerVisible="true">
<dc:Bounds x="716" y="95" width="50" height="50" />
<bpmndi:BPMNLabel>
<dc:Bounds x="721" y="76" width="41" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="BPMNShape_ship" bpmnElement="ship">
<dc:Bounds x="866" y="240" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="BPMNShape_remind" bpmnElement="remind">
<dc:Bounds x="866" y="80" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="BPMNShape_end" bpmnElement="end">
<dc:Bounds x="1066" y="102" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="1067" y="83" width="34" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="BPMNEdge_f1" bpmnElement="f1">
<di:waypoint x="116" y="120" />
<di:waypoint x="216" y="120" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="BPMNEdge_f2" bpmnElement="f2">
<di:waypoint x="266" y="120" />
<di:waypoint x="366" y="120" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="BPMNEdge_f4" bpmnElement="f4">
<di:waypoint x="466" y="120" />
<di:waypoint x="566" y="120" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="BPMNEdge_f6" bpmnElement="f6">
<di:waypoint x="616" y="120" />
<di:waypoint x="716" y="120" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="BPMNEdge_fDefault" bpmnElement="fDefault">
<di:waypoint x="766" y="120" />
<di:waypoint x="866" y="120" />
<bpmndi:BPMNLabel>
<dc:Bounds x="781" y="98" width="70" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="BPMNEdge_f8" bpmnElement="f8">
<di:waypoint x="966" y="120" />
<di:waypoint x="1066" y="120" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="BPMNEdge_f3" bpmnElement="f3">
<di:waypoint x="241" y="145" />
<di:waypoint x="241" y="280" />
<di:waypoint x="366" y="280" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="BPMNEdge_fPaid" bpmnElement="fPaid">
<di:waypoint x="741" y="145" />
<di:waypoint x="741" y="280" />
<di:waypoint x="866" y="280" />
<bpmndi:BPMNLabel>
<dc:Bounds x="746" y="206" width="32" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="BPMNEdge_f5" bpmnElement="f5">
<di:waypoint x="466" y="280" />
<di:waypoint x="591" y="280" />
<di:waypoint x="591" y="145" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="BPMNEdge_f7" bpmnElement="f7">
<di:waypoint x="966" y="280" />
<di:waypoint x="1084" y="280" />
<di:waypoint x="1084" y="138" />
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
  • Every exclusive split that has a branch without a condition declares that branch as the default flow.
  • Joins that must wait for concurrent branches use a parallel gateway, not an exclusive join.
  • Each branch of an event-based gateway leads to an intermediate catch event of type timer, message, or signal.
  • Inclusive splits have conditions on their outgoing flows, and the matching join is an inclusive gateway.