Events represent something that happens during a process: a process starts, something is waited for, a result is emitted, an exception arises, time passes. Each event combines a position (start, end, intermediate catch, intermediate throw, boundary) with an event definition that says what kind of trigger or effect is involved.
Event definitions
The engine supports the following event definition types. Not every type is valid at every position.
| Definition | XML element | Used for |
|---|
| None | (no event-definition child) | Plain start/end/throw points; the simplest form |
| Message | messageEventDefinition messageRef="..." | Send or wait for a correlated message |
| Timer | timerEventDefinition with timeDate, timeDuration, or timeCycle child | Schedule, wait, or fire on a cycle |
| Signal | signalEventDefinition signalRef="..." | Broadcast or wait for a named signal |
| Link | linkEventDefinition name="..." | In-process "goto" between throw and catch |
| Error | errorEventDefinition errorRef="..." | Throw or catch a business error |
| Escalation | escalationEventDefinition escalationRef="..." | Throw or catch an escalation up the scope hierarchy |
| Compensation | compensateEventDefinition | Trigger or handle compensation for completed activities |
| Conditional | conditionalEventDefinition with condition child | Fire when a FEEL expression turns true |
| Terminate | terminateEventDefinition | End the enclosing scope immediately |
messageRef, signalRef, errorRef, and escalationRef must reference a top-level <message> / <signal> / <error> / <escalation> declaration in the same <definitions> block — see Global definitions.
Position × definition compatibility
| Start | End | Intermediate catch | Intermediate throw | Boundary |
|---|
| None | ✓ | ✓ | — | ✓ | — |
| Message | ✓ | ✓ | ✓ | ✓ | ✓ |
| Timer | ✓ | — | ✓ | — | ✓ |
| Signal | ✓ | — | ✓ | ✓ | ✓ |
| Link | — | — | ✓ | ✓ | — |
| Error | event sub-process only | ✓ | — | — | ✓ (always interrupting) |
| Escalation | event sub-process only | ✓ | — | ✓ | ✓ |
| Compensation | event sub-process only | ✓ | — | ✓ | ✓ |
| Conditional | event sub-process only | — | — | — | ✓ |
| Terminate | — | ✓ | — | — | — |
Start events
Start events define how a process or sub-process begins.
Attributes
| Attribute | Default | Notes |
|---|
id | — | Required |
name | — | Optional |
isInterrupting | true | Applies to start events inside event sub-processes only. Ignored on top-level start events. |
Auto-start behavior
When a process is deployed, typed start events are registered so an instance is started automatically when the trigger arrives:
| Definition | Trigger |
|---|
| None | Process started explicitly via API |
| Message | A message with the matching name is published |
| Signal | A signal with the matching name is broadcast |
| Timer | The configured time arrives. Recurring expressions (R/PT1H) re-arm after each firing; one-shot (date) expressions fire once and deactivate |
Re-deploying the process under a new version deactivates the previous version's auto-start registrations and arms the new ones.
Examples
<bpmn:startEvent id="start">
<bpmn:outgoing>f1</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:startEvent id="start-msg">
<bpmn:outgoing>f1</bpmn:outgoing>
<bpmn:messageEventDefinition messageRef="Msg_Payment" />
</bpmn:startEvent>
<bpmn:startEvent id="start-timer">
<bpmn:outgoing>f1</bpmn:outgoing>
<bpmn:timerEventDefinition>
<bpmn:timeCycle xsi:type="bpmn:tFormalExpression">R/PT1H</bpmn:timeCycle>
</bpmn:timerEventDefinition>
</bpmn:startEvent>
<bpmn:startEvent id="esp-start" isInterrupting="false">
<bpmn:outgoing>f1</bpmn:outgoing>
<bpmn:messageEventDefinition messageRef="Msg_Notify" />
</bpmn:startEvent>
Validation
| Check | Severity |
|---|
| Executable process has no start event | Error |
| Start event has any incoming sequence flow (BPMN 2.0 §10.4.2) | Error |
| Error / escalation / compensation start event placed outside an event sub-process (BPMN 2.0 §10.4.2 — these triggers are only legal as the starter of an event sub-process) | Error |
| Conditional start event at top level — the engine does not auto-instantiate top-level conditional starts; use an event sub-process or external trigger | Warning |
messageRef / signalRef / errorRef / escalationRef references an unknown definition | Error |
End events
End events finish a path of execution. A process must have at least one reachable end event (or a node with no outgoing flow, which is treated as an implicit end).
Behavior by definition
| Definition | Effect |
|---|
| None | Completes the path normally |
| Message | Publishes a message, then completes. With quantum:taskDefinition set, a worker performs the dispatch; otherwise the engine publishes directly |
| Error | Throws an error; propagates up the scope hierarchy to the nearest matching error boundary or error start event in an event sub-process |
| Escalation | Throws an escalation up the scope chain to the nearest matching listener. With quantum:taskDefinition a worker performs the dispatch |
| Terminate | Cancels the nearest enclosing activity scope (sub-process, ad-hoc sub-process, or root process) and continues from that scope's outgoing flow. At the root, the entire instance terminates. A terminate inside a called process ends only the called process |
| Compensation | Triggers compensation for completed activities in scope, or for the activity named by activityRef |
Examples
<bpmn:endEvent id="end">
<bpmn:incoming>f_last</bpmn:incoming>
</bpmn:endEvent>
<bpmn:endEvent id="end-error">
<bpmn:incoming>f_err</bpmn:incoming>
<bpmn:errorEventDefinition errorRef="Err_Timeout" />
</bpmn:endEvent>
<bpmn:endEvent id="end-terminate">
<bpmn:incoming>f_abort</bpmn:incoming>
<bpmn:terminateEventDefinition />
</bpmn:endEvent>
<bpmn:endEvent id="end-msg">
<bpmn:extensionElements>
<quantum:taskDefinition type="send-notification" />
</bpmn:extensionElements>
<bpmn:incoming>f_notify</bpmn:incoming>
<bpmn:messageEventDefinition messageRef="Msg_Done" />
</bpmn:endEvent>
Validation
| Check | Severity |
|---|
| End event has any outgoing sequence flow (BPMN 2.0 §10.4.3) | Error |
messageRef / errorRef / escalationRef references an unknown definition | Error |
Message end event with no messageRef and no quantum:taskDefinition | Warning (publishes a nameless message) |
Escalation end event with no escalationRef and no quantum:taskDefinition | Warning (throws a nameless escalation) |
Intermediate catch events pause the token until an external trigger arrives, then advance.
Behavior by definition
| Definition | Behavior |
|---|
| Message | Waits for a correlated message matching the referenced name. If a buffered message is already available it fires immediately |
Timer — timeDuration | Waits the specified ISO 8601 duration from the moment the event is reached |
Timer — timeDate | Waits until the specified ISO 8601 datetime |
Timer — timeCycle | Fires repeatedly on the cycle |
| Signal | Waits for a broadcast matching the referenced name; checks the buffer first |
| Link | Receives control from a matching link throw event of the same name in the same scope. Acts as a goto target |
A catch event placed immediately after an event-based gateway must have exactly one incoming flow (from the gateway).
Examples
<bpmn:intermediateCatchEvent id="catch-msg" name="Wait for Payment">
<bpmn:incoming>f1</bpmn:incoming>
<bpmn:outgoing>f2</bpmn:outgoing>
<bpmn:messageEventDefinition messageRef="Msg_Payment" />
</bpmn:intermediateCatchEvent>
<bpmn:intermediateCatchEvent id="wait-5m" name="Wait 5 min">
<bpmn:incoming>f1</bpmn:incoming>
<bpmn:outgoing>f2</bpmn:outgoing>
<bpmn:timerEventDefinition>
<bpmn:timeDuration xsi:type="bpmn:tFormalExpression">PT5M</bpmn:timeDuration>
</bpmn:timerEventDefinition>
</bpmn:intermediateCatchEvent>
<bpmn:intermediateCatchEvent id="catch-signal" name="Receive Abort">
<bpmn:incoming>f1</bpmn:incoming>
<bpmn:outgoing>f2</bpmn:outgoing>
<bpmn:signalEventDefinition signalRef="Sig_Abort" />
</bpmn:intermediateCatchEvent>
<bpmn:intermediateCatchEvent id="catch-link" name="Land">
<bpmn:outgoing>f3</bpmn:outgoing>
<bpmn:linkEventDefinition name="LinkA" />
</bpmn:intermediateCatchEvent>
Validation
| Check | Severity |
|---|
| No event definition present | Error |
| Catch event has anything other than exactly one outgoing sequence flow (BPMN 2.0 §10.5.4 — intermediate events have one input, one output) | Error |
| Catch event after an event-based gateway has more than one incoming flow | Error |
messageRef / signalRef references an unknown definition | Error |
Intermediate throw events emit something — a message, signal, escalation, link, or compensation trigger — and then advance immediately. A throw with no event definition is a pass-through.
Behavior by definition
| Definition | Behavior |
|---|
| None | Pure pass-through |
| Message | Publishes the message with the current scope variables. If quantum:taskDefinition is also set, switches to external-job mode (see below) |
| Signal | Broadcasts the signal to all subscribers |
| Link | Transfers control to the matching link catch in the same scope. Acts as a goto |
| Escalation | Throws an escalation up to the nearest matching listener |
| Compensation | Triggers compensation; activityRef can target a specific completed activity |
Execution modes (apply to every throw kind)
A throw event with quantum:taskDefinition type="..." switches into worker-driven mode regardless of which event definition is attached: the engine creates a job, the worker performs the actual publish/throw, and the throw advances when the worker reports completion. In this mode the messageRef / escalationRef / etc. become optional — the worker controls what is dispatched.
| Mode | When active | Behavior |
|---|
| Direct dispatch | No quantum:taskDefinition | Engine publishes / throws immediately and advances |
| External job | quantum:taskDefinition type="..." is set | Engine creates a persistent job; throw advances when the worker completes the job |
The same applies to message and escalation end events.
Examples
<bpmn:intermediateThrowEvent id="throw-signal" name="Broadcast Abort">
<bpmn:incoming>f1</bpmn:incoming>
<bpmn:outgoing>f2</bpmn:outgoing>
<bpmn:signalEventDefinition signalRef="Sig_Abort" />
</bpmn:intermediateThrowEvent>
<bpmn:intermediateThrowEvent id="throw-esc" name="Escalate">
<bpmn:incoming>f1</bpmn:incoming>
<bpmn:outgoing>f2</bpmn:outgoing>
<bpmn:escalationEventDefinition escalationRef="Esc_Review" />
</bpmn:intermediateThrowEvent>
<bpmn:intermediateThrowEvent id="throw-link" name="Jump">
<bpmn:incoming>f1</bpmn:incoming>
<bpmn:linkEventDefinition name="LinkA" />
</bpmn:intermediateThrowEvent>
<bpmn:intermediateThrowEvent id="throw-comp" name="Compensate All">
<bpmn:incoming>f1</bpmn:incoming>
<bpmn:outgoing>f2</bpmn:outgoing>
<bpmn:compensateEventDefinition />
</bpmn:intermediateThrowEvent>
Validation
| Check | Severity |
|---|
messageRef / signalRef / escalationRef references an unknown definition | Error |
Message throw with no messageRef and no quantum:taskDefinition (publish has no name to correlate against) | Error |
Escalation throw with no escalationRef, no inline escalationCode, and no quantum:taskDefinition (no listener can match) | Error |
Link throw has no matching link catch with the same name in the same scope | Error |
Boundary events
Boundary events are attached to an activity (task, sub-process, or call activity) and fire while the activity is running.
Attributes
| Attribute | Default | Notes |
|---|
id | — | Required |
name | — | Optional |
attachedToRef | — | Required. ID of the host activity (must be in the same scope) |
cancelActivity | true | true = interrupting (host is cancelled, only the boundary path continues); false = non-interrupting (host continues; a parallel token starts from the boundary). Ignored on compensation boundaries |
Behavior by definition
| Definition | Notes |
|---|
| Message | Fires when a correlated message arrives while the host is active |
| Timer | timeDuration and timeDate fire once. timeCycle (e.g. R3/PT1M) fires repeatedly and is non-interrupting only |
| Error | Always interrupting. Fires when the host throws a matching error |
| Signal | Fires when the matching signal is broadcast while the host is active |
| Escalation | Fires when the host throws a matching escalation |
| Conditional | Fires when the FEEL condition evaluates to true while the host is active |
| Compensation | Marks this boundary as the trigger for a compensation handler. Linked to the handler activity by an <association> element. Does not use cancelActivity — fires only when compensation is explicitly thrown for the host (after the host has completed), and never cancels the host |
Examples
<bpmn:boundaryEvent id="timer-boundary" attachedToRef="long-task" cancelActivity="true">
<bpmn:outgoing>f_timeout</bpmn:outgoing>
<bpmn:timerEventDefinition>
<bpmn:timeDuration xsi:type="bpmn:tFormalExpression">PT30M</bpmn:timeDuration>
</bpmn:timerEventDefinition>
</bpmn:boundaryEvent>
<bpmn:boundaryEvent id="msg-boundary" attachedToRef="approval-task" cancelActivity="false">
<bpmn:outgoing>f_notify</bpmn:outgoing>
<bpmn:messageEventDefinition messageRef="Msg_Reminder" />
</bpmn:boundaryEvent>
<bpmn:boundaryEvent id="err-boundary" attachedToRef="service-task" cancelActivity="true">
<bpmn:outgoing>f_error</bpmn:outgoing>
<bpmn:errorEventDefinition errorRef="Err_Timeout" />
</bpmn:boundaryEvent>
<bpmn:boundaryEvent id="comp-boundary" attachedToRef="book-hotel">
<bpmn:compensateEventDefinition />
</bpmn:boundaryEvent>
<bpmn:serviceTask id="cancel-hotel" name="Cancel Hotel" isForCompensation="true">
<bpmn:extensionElements>
<quantum:taskDefinition type="cancel-hotel-worker" />
</bpmn:extensionElements>
</bpmn:serviceTask>
<bpmn:association id="assoc1" sourceRef="comp-boundary" targetRef="cancel-hotel" />
<bpmn:boundaryEvent id="cycle-boundary" attachedToRef="long-task" cancelActivity="false">
<bpmn:outgoing>f_tick</bpmn:outgoing>
<bpmn:timerEventDefinition>
<bpmn:timeCycle>R3/PT1M</bpmn:timeCycle>
</bpmn:timerEventDefinition>
</bpmn:boundaryEvent>
Validation
| Check | Severity |
|---|
attachedToRef is empty or doesn't resolve to an activity in the same scope | Error |
| No event definition present | Error |
Error boundary has cancelActivity="false" | Error |
Timer boundary has none of timeDuration/timeDate/timeCycle | Error |
Timer boundary uses timeCycle while interrupting | Error |
Timer boundary mixes timeCycle with timeDuration or timeDate | Warning (timeCycle wins) |
Conditional boundary has empty condition | Error |
| Compensation boundary has no associated handler activity | Error |
Compensation handler is not marked isForCompensation="true" | Error |
messageRef / signalRef / errorRef / escalationRef references an unknown definition | Error |