Events
An event represents something that happens during a business process — a message arrives, time passes, an error occurs. Unlike activities, events do not perform work of their own: catching events wait for their trigger to occur, while throwing events produce a result and continue immediately.
Two things define an event: its position in the process (start, intermediate, boundary, or end) and its type (what triggers it or what it produces). The same types reappear at every position, so each type is documented on a single page covering all its positions — this page describes the behavior the positions share, and how events handle variables.
Green icons are supported and link to their documentation.
| Type | Start | Intermediate | Boundary | End | ||
|---|---|---|---|---|---|---|
| Normal | Catch | Throw | Interrupting | Non-Interrupting | Normal | |
| None | ||||||
| Message | ||||||
| Timer | ||||||
| Escalation | ||||||
| Conditional | ||||||
| Link | ||||||
| Error | ||||||
| Signal | ||||||
| Compensation | ||||||
None Intermediate Throw Event, Escalation, Conditional, Signal, Compensation, Cancel
Start events
A start event defines the beginning of a process instance. It has no incoming sequence flows and exactly one outgoing sequence flow, and is rendered as a thin single-line circle. When its trigger occurs, a new process instance is created and a token starts moving along the outgoing flow. A process can have multiple start events, each with a different trigger.
The trigger depends on the type:
- None start event — no event definition is attached. The process is started explicitly by a caller, typically through the REST or gRPC API.
- Message start event — a new instance is created each time a matching message is published.
- Timer start event — instances are created on a schedule, without any external trigger.
At the top level, none and timer start events can use zenbpm:output mappings to initialize or derive root process variables before the outgoing flow runs. A none start event evaluates mappings against the variables supplied when the instance is created; a timer start creates an instance with an empty root scope, which mappings can initialize from literals or expressions. Mapped values add to or overwrite existing root variables.
For a top-level message start event, output mappings evaluate against the message payload before the instance is created. Without mappings, the full payload becomes the instance's initial variables; with mappings, only the mapped values do. Start events do not support zenbpm:input mappings; variables supplied through the create-instance API already belong to the root process scope.
Start events also appear inside an Event sub process, where message, timer, and error triggers are supported and the start event may be non-interrupting.
Intermediate events
Intermediate events occur between the start and end of a process and are rendered as a double-line circle. They come in two directions:
- Catch events pause the flow: the token waits at the event until the trigger occurs — a message arrives or a timer fires. Message and timer catch events can also follow an Event-based gateway, letting the process react to whichever trigger occurs first.
- Throw events execute as soon as the token reaches them and continue onward — sending a message or jumping to a link target.
Boundary events
A boundary event is attached to the border of an activity via attachedToRef and models what should happen if its trigger occurs while that activity is active. It has no incoming flow and one outgoing flow that defines the alternative path. The engine subscribes to the trigger when the activity starts waiting and removes the subscription when the activity completes — a boundary event never fires for an already-completed activity.
Boundary events come in two flavors, distinguished by the cancelActivity attribute and the border style:
- Interrupting (solid border, the default) — the attached activity is cancelled, together with its jobs, child instances, and other boundary subscriptions, and the token moves along the boundary event's outgoing flow.
- Non-interrupting (dashed border,
cancelActivity="false") — the activity keeps running and a new parallel token is created on the outgoing flow.
Boundary events can be attached to Service tasks, Send tasks, User tasks, Business rule tasks, Receive tasks, Sub processes, and Call activities. Supported triggers are message, timer, and error (error is always interrupting).
End events
An end event marks the completion of a process path. It has no outgoing sequence flows and is rendered as a thick single-line circle. A process may have multiple end events; the process instance completes once all of its active tokens have reached one.
What happens when the token arrives depends on the type:
- None end event — the path simply ends without producing any result.
- Message end event — a message is sent before the path ends.
- Error end event — the path ends by throwing a BPMN error that an error boundary event on an enclosing scope can catch.
- Terminate end event (thick circle with a filled dot) — the entire process instance is cancelled immediately: all remaining tokens, active jobs, subscriptions, and called child instances are terminated, regardless of other active paths.
Variables
Events handle variables differently from activities. The event type determines which mappings apply:
| Event kind | Mappings | Behavior |
|---|---|---|
| Catching events that receive a payload — message start, message catch, message boundary, error boundary | zenbpm:output | Without output mappings, the entire payload is propagated to the catching scope as-is. With output mappings, only mapped values are propagated. For message starts, these become the new instance's initial variables. This is the opposite default from activities, which propagate nothing unmapped. |
| Throwing message events — message intermediate throw, message end | zenbpm:input / zenbpm:output | Executed as a job, exactly like a Send task: input mappings prepare the variables the worker sees, output mappings propagate the worker's result following the activity rules. |
| Top-level none start events | zenbpm:output | Evaluate mappings against create-instance root variables and add or overwrite mapped values before the outgoing flow. Without mappings, the supplied variables remain unchanged. |
| Top-level timer start events | zenbpm:output | Carry no payload. Mappings can initialize root variables before the outgoing flow; a scheduled instance starts with an empty root scope. |
| Timer boundary events | zenbpm:output | Carry no payload. When the timer fires, mappings evaluate against the containing process scope and propagate mapped values to it. Without mappings, variables remain unchanged. |
| Timer intermediate catch events | — | Carry no payload and do not apply output mappings; process variables remain unchanged, including when the timer follows an event-based gateway. |
| Link throw and catch events | zenbpm:output | Carry no payload. Each event can derive or overwrite process variables; the catch event can read values mapped by the throw event. Without mappings, variables remain unchanged. |
See Variables for the full propagation rules.
Related documentation
- Variables — output-mapping propagation rules for catching events and activities.
- Message events, Timer events, Error events, Link events — the individual event types.
- Event-based gateway — branching on the first of several catch events to trigger.
XML example
The events with no configuration beyond their definition: a none start event, a none end event, and a terminate end event cancelling the whole instance on an alternative path:
<bpmn:startEvent id="Start_Order" name="Order placed">
<bpmn:outgoing>Flow_Process</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:endEvent id="End_Fulfilled" name="Order fulfilled">
<bpmn:incoming>Flow_Done</bpmn:incoming>
</bpmn:endEvent>
<bpmn:endEvent id="End_Cancelled" name="Order cancelled">
<bpmn:incoming>Flow_Cancel</bpmn:incoming>
<bpmn:terminateEventDefinition />
</bpmn:endEvent>