Join or fork gateway.
A parallel gateway with more than one incoming sequence flow is converging: it monitors its upstream peer activities and completes once they have all settled, rather than completing as soon as the expected number of inbound flows have been touched. Peers are discovered during the process shake.
This avoids stalls in the edge case where the same inbound flow may be touched more than once before all peers have reported. The gateway only starts converging once an inbound flow is taken, so it always completes by taking its outbound flows; a join is never discarded because a branch was skipped.
A parallel gateway with a single incoming sequence flow has nothing to converge. As BPMN 2.0 prescribes, it fires on every inbound token without awaiting upstream peers, so an uncontrolled merge upstream (an activity with multiple incoming flows) fires it once per token. It does not publish activity.converge and does not trigger the process shake.
Peers are collected per inbound flow. An inbound flow that has not been touched when the gateway starts converging also awaits the peers of any parallel gateway upstream of it, so a branch that is still running behind another parallel gateway holds the join. An already touched inbound flow only awaits its immediate peers, which keeps a later token on the same flow, e.g. from a loop back, a separate firing.
A parallel gateway is the only element that gives true barrier semantics: a converging parallel gateway waits for every concurrent upstream branch to settle before it continues. Reach for it when you must converge all flows before proceeding — e.g. two parallel branches that both have to finish before the next step may start.
If you do not need that guarantee, prefer a cheaper construct:
- An exclusive gateway or an uncontrolled merge (an activity with multiple incoming flows) continues as soon as any inbound flow is taken — it does not wait, and does not trigger the costs below.
- An inclusive gateway converges with the same peer monitoring and costs the same as a parallel gateway; it differs only in evaluating its conditional outbound flows.
- For "first one wins" semantics use an event-based gateway.
Picking a parallel join only when you genuinely need the barrier keeps the common path on the cheaper machinery.
A converging parallel gateway is more expensive than the other gateways, by design:
- Process shake on start. To learn which upstream activities are its peers, the presence of a converging parallel gateway — one with more than one incoming sequence flow — forces a graph shake when the process starts. A process where every gateway only forks is not shaken. Exclusive and event-based joins do not, but an inclusive gateway does since it converges the same way. The shake walks the reachable graph, so its cost grows with graph size, and on graphs with many branching gateways in series it can grow super-linearly (it enumerates paths). The shake result is cached on the context and reused, so it runs once per context rather than once per run — reuse the same
Context/Definitionsource across executions so the shake amortizes instead of repeating. - Peer monitoring at runtime. While converging, the gateway watches all of its discovered peer activities until they settle (see Converging behaviour above), which is more work than counting inbound flows.
The upside is correctness on hard topologies and a large win elsewhere: because joins no longer rely on discarded flows arriving, dead branches are not propagated as discards. On branchy or looping diagrams that is dramatically cheaper than discarding every dead-path flow on every run.
Rule of thumb: a parallel join is the right tool when you must synchronise all branches; avoid it on hot paths where an exclusive merge would do, and reuse the context so the one-time shake is paid once.
activity.converge: The converging parallel gateway is collecting inbound and monitoring peers