Skip to main content

Real-Time Notifications via BPMN Events

The Mechanism​

Stateway delivers real-time push notifications to the frontend through Intermediate Message Throw Events in your BPMN diagram. When the process reaches one of these elements, the SDK emits a notification event with the element's name as the message.

No additional Stateway configuration is needed — the behavior is derived directly from the diagram.

How to Add to Your Diagram​

In your BPMN modeler, insert an Intermediate Throw Event of type Message at the point in the flow where you want to notify the user. Give the element a descriptive name — that name becomes the message received by the frontend.

[Submit Request] ──→ [Analyze Credit] ──→ (✉ Analysis complete) ──→ [Sign Contract]
userTask serviceTask intermediateThrowEvent userTask

Receiving in the SDK​

sw.on('notification', ({ message, variables }) => {
// message: "Analysis complete"
showToast(message);
});

// When the next human task arrives:
sw.on('task.assigned', (task) => {
hideSpinner();
renderTaskForm(task);
});

Including Data in Notifications​

By default, notifications include no variables. To include process data, declare stateway:variableFilter in the element's extensionElements:

<bpmn:intermediateThrowEvent id="notify_analysis" name="Analysis complete">
<bpmn:extensionElements>
<stateway:variableFilter variables="creditScore,approvedLimit" />
</bpmn:extensionElements>
<bpmn:messageEventDefinition messageRef="msg_analysis_done" />
</bpmn:intermediateThrowEvent>
sw.on('notification', ({ message, variables }) => {
// message: "Analysis complete"
// variables: { creditScore: 720, approvedLimit: 50000 }
showToast(`${message}. Score: ${variables.creditScore}`);
});

Notifications That Are Also Process Events​

When the throw event references a message (messageRef) or declares stateway:eventCorrelation, it also throws that named event to its own instance. For example, it can interrupt a task on a parallel branch (see Throwing Named Events from a Process). The notification then carries the event name in eventName, so the frontend can tell a process event from a plain status message:

sw.on('notification', ({ message, eventName }) => {
if (eventName === 'ticketCancelled') {
showBanner('This ticket was cancelled');
return;
}
showToast(message);
});

A message endEvent that throws a named event publishes the same notification. A plain endEvent publishes none.

Feedback on Automatic Steps​

The most common pattern is using notifications to provide feedback while automatic steps (service tasks, timers) run between two human tasks:

sw.on('task.completed', ({ next }) => {
if (next.kind === 'automatic') {
showSpinner(`Processing: ${next.elementName}...`);
}
if (next.kind === 'timer') {
showCountdown('Next step in', next.estimatedFireAt);
}
});

sw.on('notification', ({ message }) => {
hideSpinner();
showToast(message);
// task.assigned arrives next with the next human task
});

Naming Recommendations​

Name elements for the end user, not the technical process:

❌ Avoid✅ Prefer
invoke_erp_callbackOrder registered in system
payment_service_responsePayment confirmed
notify_step_3_completeProposal sent to client

Who Receives a Notification​

A notification goes to every connected user who is a participant of the instance:

  • the user who started the instance with startProcess;
  • every user who is the assignee of one of the instance's tasks, whether the task is open, completed or cancelled. That includes the user who claimed a pool task, the user a task was assigned or delegated to, and a fixed assignee in the definition.

Candidates who never claimed the task (candidateUsers, candidateGroups) do not receive it, even if they saw the task in their work list. A user who releases a claim stops receiving notifications from that instance, unless they still qualify through another task or as the starter. The same users receive instance.completed.

The variableFilter and the session's variable_visibility apply to every recipient in the same way.

Limitations​

Every Intermediate Throw Event generates a WebSocket push, and so does an End Event that throws a named event. Other end events, catch events and boundary events publish no notification. Only the instance's participants receive it; see Who Receives a Notification.