The elements · 04 · 9 min

Gateways

Diamonds route tokens. They never perform work, never consume time, and never make a decision themselves.

If the gateway is not asking the question, something upstream must have answered it. The three types differ in what they do with that answer.

GatewaySplit behaviourJoin behaviour
Exclusive (XOR)Takes exactly one outgoing flow: the first whose condition is true.Does not wait.
Parallel (AND)Takes all outgoing flows. One token in, N tokens out.Waits for all incoming flows.
Inclusive (OR)Takes every flow whose condition is true, one, several, or all.Waits for every token that can still arrive. The hardest to reason about.
Event-basedDoes not evaluate data. Routes to whichever event happens first.Rarely used as a join.
ComplexCustom conditions ("any 3 of 5 approvals"). Rare, usually a sign the model should be restructured.,

The default flow covers the else case

An exclusive gateway whose conditions are all false has nowhere to send the token. A default flow, marked with a backslash, is taken when nothing else matches.

Exclusive gateway with a default flow

After "Check invoice", the gateway "Invoice correct?" routes yes to "Schedule payment"; the default flow ("otherwise") catches every other case.

Invoice receivedCheck invoiceInvoice correct?Schedule paymentRaise queryyesotherwise

Event-based gateway: the race

This is the one people under-use. It models “whichever comes first”: a reply, or a timeout. The token waits at the gateway; whichever event fires first wins and the other path is discarded.

Event-based gateway, whichever happens first

After "Send invoice", an event-based gateway waits: "Payment received" leads to "Close case", "14 days" to "Send reminder". Whichever comes first wins.

Invoice dueSend invoicePayment received14 daysClose caseSend reminder

This is how you model “escalate after 14 days” without inventing a polling loop.

After this module you can

  • Choose between exclusive, parallel, inclusive and event-based gateways
  • Explain why a parallel join waits and an exclusive join does not
  • Use a default flow to cover the else case
← TokensSkip without completing