Subscription cancellation BPMN example
Cancellation is the one customer journey that regulators, finance, and retention teams all care about at once, which makes it worth mapping precisely. Rules in several markets now require cancelling to be as easy as signing up, so the process cannot hide steps. It usually goes wrong in two ways: retention offers that block the exit and infuriate the customer, and billing that keeps charging after the account is closed.
The model is a single pool with three lanes: Customer support, Retention, and Billing. Two exclusive gateways drive it, one for the retention offer and one for whether the customer is owed credit on the final balance. Notice that the retention attempt is a single offer with a clean exit: the default path leads to cancellation, so declining the offer never traps the token in a persuasion loop.
Standard BPMN 2.0 interchange XML: opens in Camunda Modeler, Signavio, Bizagi, and any other compliant tool.
The process at a glance
How to read this diagram
The flow opens in the Customer support lane when a cancellation is requested, and the agent captures the cancellation reason for later analysis. In the Retention lane, one retention offer is presented, and the gateway "Offer accepted?" resolves it: on the Yes branch a discount is applied and the process ends immediately at "Subscription retained". The default No branch respects the customer decision and moves to Billing.
Billing work then runs in a fixed order: the subscription is cancelled first, so no further charges can occur, and the final balance is calculated next. The gateway "Credit owed to customer?" checks the result: Yes triggers a refund of the unused period before confirmation, while the default No branch goes straight to it. A confirmation message from Customer support closes the process at "Subscription ended", giving the model two end states that mirror the two commercial outcomes.
BPMN elements used
| Element | Count | In this diagram |
|---|---|---|
| Start event | 1 | Cancellation requested |
| End event | 2 | Subscription retained, Subscription ended |
| Task | 1 | Calculate final balance |
| User task | 1 | Capture cancellation reason |
| Service task | 3 | Apply retention discount, Cancel subscription, Refund unused period |
| Send task | 2 | Present retention offer, Confirm cancellation |
| Exclusive gateway | 2 | Offer accepted?, Credit owed to customer? |
View the BPMN 2.0 XML for this diagram
<?xml version="1.0" encoding="UTF-8"?>
<bpmn2:definitions xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="Definitions_1" targetNamespace="http://bpmn.io/schema/bpmn" exporter="swimdraft" exporterVersion="1.0">
<bpmn2:collaboration id="Collaboration_1">
<bpmn2:participant id="pool_sc" name="Subscription cancellation" processRef="Process_pool_sc" />
</bpmn2:collaboration>
<bpmn2:process id="Process_pool_sc" isExecutable="false">
<bpmn2:laneSet id="LaneSet_pool_sc">
<bpmn2:lane id="lane_sc_sup" name="Customer support">
<bpmn2:flowNodeRef>start_sc</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>t_sc_reason</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>t_sc_confirm</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>end_sc_ended</bpmn2:flowNodeRef>
</bpmn2:lane>
<bpmn2:lane id="lane_sc_ret" name="Retention">
<bpmn2:flowNodeRef>t_sc_offer</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>g_sc_accept</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>t_sc_apply</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>end_sc_retained</bpmn2:flowNodeRef>
</bpmn2:lane>
<bpmn2:lane id="lane_sc_bill" name="Billing">
<bpmn2:flowNodeRef>t_sc_cancel</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>t_sc_balance</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>g_sc_credit</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>t_sc_refund</bpmn2:flowNodeRef>
</bpmn2:lane>
</bpmn2:laneSet>
<bpmn2:startEvent id="start_sc" name="Cancellation requested">
<bpmn2:outgoing>f_sc1</bpmn2:outgoing>
</bpmn2:startEvent>
<bpmn2:userTask id="t_sc_reason" name="Capture cancellation reason">
<bpmn2:incoming>f_sc1</bpmn2:incoming>
<bpmn2:outgoing>f_sc2</bpmn2:outgoing>
</bpmn2:userTask>
<bpmn2:sendTask id="t_sc_offer" name="Present retention offer">
<bpmn2:incoming>f_sc2</bpmn2:incoming>
<bpmn2:outgoing>f_sc3</bpmn2:outgoing>
</bpmn2:sendTask>
<bpmn2:exclusiveGateway id="g_sc_accept" name="Offer accepted?" default="f_sc5">
<bpmn2:incoming>f_sc3</bpmn2:incoming>
<bpmn2:outgoing>f_sc4</bpmn2:outgoing>
<bpmn2:outgoing>f_sc5</bpmn2:outgoing>
</bpmn2:exclusiveGateway>
<bpmn2:serviceTask id="t_sc_apply" name="Apply retention discount">
<bpmn2:incoming>f_sc4</bpmn2:incoming>
<bpmn2:outgoing>f_sc6</bpmn2:outgoing>
</bpmn2:serviceTask>
<bpmn2:endEvent id="end_sc_retained" name="Subscription retained">
<bpmn2:incoming>f_sc6</bpmn2:incoming>
</bpmn2:endEvent>
<bpmn2:serviceTask id="t_sc_cancel" name="Cancel subscription">
<bpmn2:incoming>f_sc5</bpmn2:incoming>
<bpmn2:outgoing>f_sc7</bpmn2:outgoing>
</bpmn2:serviceTask>
<bpmn2:task id="t_sc_balance" name="Calculate final balance">
<bpmn2:incoming>f_sc7</bpmn2:incoming>
<bpmn2:outgoing>f_sc8</bpmn2:outgoing>
</bpmn2:task>
<bpmn2:exclusiveGateway id="g_sc_credit" name="Credit owed to customer?" default="f_sc10">
<bpmn2:incoming>f_sc8</bpmn2:incoming>
<bpmn2:outgoing>f_sc9</bpmn2:outgoing>
<bpmn2:outgoing>f_sc10</bpmn2:outgoing>
</bpmn2:exclusiveGateway>
<bpmn2:serviceTask id="t_sc_refund" name="Refund unused period">
<bpmn2:incoming>f_sc9</bpmn2:incoming>
<bpmn2:outgoing>f_sc11</bpmn2:outgoing>
</bpmn2:serviceTask>
<bpmn2:sendTask id="t_sc_confirm" name="Confirm cancellation">
<bpmn2:incoming>f_sc10</bpmn2:incoming>
<bpmn2:incoming>f_sc11</bpmn2:incoming>
<bpmn2:outgoing>f_sc12</bpmn2:outgoing>
</bpmn2:sendTask>
<bpmn2:endEvent id="end_sc_ended" name="Subscription ended">
<bpmn2:incoming>f_sc12</bpmn2:incoming>
</bpmn2:endEvent>
<bpmn2:sequenceFlow id="f_sc1" sourceRef="start_sc" targetRef="t_sc_reason" />
<bpmn2:sequenceFlow id="f_sc2" sourceRef="t_sc_reason" targetRef="t_sc_offer" />
<bpmn2:sequenceFlow id="f_sc3" sourceRef="t_sc_offer" targetRef="g_sc_accept" />
<bpmn2:sequenceFlow id="f_sc4" name="Yes" sourceRef="g_sc_accept" targetRef="t_sc_apply">
<bpmn2:conditionExpression xsi:type="bpmn2:tFormalExpression">Yes</bpmn2:conditionExpression>
</bpmn2:sequenceFlow>
<bpmn2:sequenceFlow id="f_sc5" name="No" sourceRef="g_sc_accept" targetRef="t_sc_cancel" />
<bpmn2:sequenceFlow id="f_sc6" sourceRef="t_sc_apply" targetRef="end_sc_retained" />
<bpmn2:sequenceFlow id="f_sc7" sourceRef="t_sc_cancel" targetRef="t_sc_balance" />
<bpmn2:sequenceFlow id="f_sc8" sourceRef="t_sc_balance" targetRef="g_sc_credit" />
<bpmn2:sequenceFlow id="f_sc9" name="Yes" sourceRef="g_sc_credit" targetRef="t_sc_refund">
<bpmn2:conditionExpression xsi:type="bpmn2:tFormalExpression">Yes</bpmn2:conditionExpression>
</bpmn2:sequenceFlow>
<bpmn2:sequenceFlow id="f_sc10" name="No" sourceRef="g_sc_credit" targetRef="t_sc_confirm" />
<bpmn2:sequenceFlow id="f_sc11" sourceRef="t_sc_refund" targetRef="t_sc_confirm" />
<bpmn2:sequenceFlow id="f_sc12" sourceRef="t_sc_confirm" targetRef="end_sc_ended" />
</bpmn2:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Collaboration_1">
<bpmndi:BPMNShape id="pool_sc_di" bpmnElement="pool_sc" isHorizontal="true">
<dc:Bounds x="20" y="20" width="1570" height="390" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="lane_sc_sup_di" bpmnElement="lane_sc_sup" isHorizontal="true">
<dc:Bounds x="50" y="20" width="1540" height="130" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="lane_sc_ret_di" bpmnElement="lane_sc_ret" isHorizontal="true">
<dc:Bounds x="50" y="150" width="1540" height="130" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="lane_sc_bill_di" bpmnElement="lane_sc_bill" isHorizontal="true">
<dc:Bounds x="50" y="280" width="1540" height="130" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="start_sc_di" bpmnElement="start_sc">
<dc:Bounds x="112" y="59" width="36" height="36" />
<bpmndi:BPMNLabel><dc:Bounds x="73" y="101" width="115" height="14" /></bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="t_sc_reason_di" bpmnElement="t_sc_reason">
<dc:Bounds x="230" y="37" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="t_sc_offer_di" bpmnElement="t_sc_offer">
<dc:Bounds x="380" y="167" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="g_sc_accept_di" bpmnElement="g_sc_accept">
<dc:Bounds x="555" y="182" width="50" height="50" />
<bpmndi:BPMNLabel><dc:Bounds x="540" y="162" width="81" height="14" /></bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="t_sc_apply_di" bpmnElement="t_sc_apply">
<dc:Bounds x="680" y="167" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="end_sc_retained_di" bpmnElement="end_sc_retained">
<dc:Bounds x="862" y="189" width="36" height="36" />
<bpmndi:BPMNLabel><dc:Bounds x="827" y="231" width="106" height="14" /></bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="t_sc_cancel_di" bpmnElement="t_sc_cancel">
<dc:Bounds x="680" y="297" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="t_sc_balance_di" bpmnElement="t_sc_balance">
<dc:Bounds x="830" y="297" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="g_sc_credit_di" bpmnElement="g_sc_credit">
<dc:Bounds x="1005" y="312" width="50" height="50" />
<bpmndi:BPMNLabel><dc:Bounds x="966" y="292" width="128" height="14" /></bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="t_sc_refund_di" bpmnElement="t_sc_refund">
<dc:Bounds x="1130" y="297" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="t_sc_confirm_di" bpmnElement="t_sc_confirm">
<dc:Bounds x="1280" y="37" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="end_sc_ended_di" bpmnElement="end_sc_ended">
<dc:Bounds x="1462" y="59" width="36" height="36" />
<bpmndi:BPMNLabel><dc:Bounds x="1432" y="101" width="97" height="14" /></bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="f_sc1_di" bpmnElement="f_sc1">
<di:waypoint x="148" y="77" />
<di:waypoint x="230" y="77" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="f_sc2_di" bpmnElement="f_sc2">
<di:waypoint x="330" y="77" />
<di:waypoint x="360" y="77" />
<di:waypoint x="360" y="207" />
<di:waypoint x="380" y="207" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="f_sc3_di" bpmnElement="f_sc3">
<di:waypoint x="480" y="207" />
<di:waypoint x="555" y="207" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="f_sc4_di" bpmnElement="f_sc4">
<di:waypoint x="605" y="207" />
<di:waypoint x="680" y="207" />
<bpmndi:BPMNLabel><dc:Bounds x="611" y="187" width="21" height="14" /></bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="f_sc5_di" bpmnElement="f_sc5">
<di:waypoint x="605" y="207" />
<di:waypoint x="660" y="207" />
<di:waypoint x="660" y="337" />
<di:waypoint x="680" y="337" />
<bpmndi:BPMNLabel><dc:Bounds x="611" y="213" width="17" height="14" /></bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="f_sc6_di" bpmnElement="f_sc6">
<di:waypoint x="780" y="207" />
<di:waypoint x="862" y="207" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="f_sc7_di" bpmnElement="f_sc7">
<di:waypoint x="780" y="337" />
<di:waypoint x="830" y="337" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="f_sc8_di" bpmnElement="f_sc8">
<di:waypoint x="930" y="337" />
<di:waypoint x="1005" y="337" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="f_sc9_di" bpmnElement="f_sc9">
<di:waypoint x="1055" y="337" />
<di:waypoint x="1130" y="337" />
<bpmndi:BPMNLabel><dc:Bounds x="1061" y="317" width="21" height="14" /></bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="f_sc10_di" bpmnElement="f_sc10">
<di:waypoint x="1055" y="337" />
<di:waypoint x="1110" y="337" />
<di:waypoint x="1110" y="286" />
<di:waypoint x="1260" y="286" />
<di:waypoint x="1260" y="77" />
<di:waypoint x="1280" y="77" />
<bpmndi:BPMNLabel><dc:Bounds x="1061" y="343" width="17" height="14" /></bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="f_sc11_di" bpmnElement="f_sc11">
<di:waypoint x="1230" y="337" />
<di:waypoint x="1260" y="337" />
<di:waypoint x="1260" y="77" />
<di:waypoint x="1280" y="77" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="f_sc12_di" bpmnElement="f_sc12">
<di:waypoint x="1380" y="77" />
<di:waypoint x="1462" y="77" />
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn2:definitions>Frequently asked questions
Why does the model cancel the subscription before calculating the balance?
Ordering matters in BPMN because sequence flows are commitments about time. Cancelling first guarantees the customer cannot be billed again while finance works out the closing position, which is the failure customers complain about most. Reversing the two tasks would be a valid diagram but a worse process, and the model should encode the safer order.
Should the retention offer be allowed to repeat with a loop?
You could loop back to "Present retention offer" after a No, but consumer protection rules increasingly treat repeated obstruction of cancellation as a dark pattern. A single offer with the default flow leading to cancellation is both simpler to read and easier to defend. If you must model a second offer, cap it explicitly with its own gateway.
Where would a notice period fit in this model?
Insert a timer intermediate catch event between "Offer accepted?" and "Cancel subscription", set to the contractual notice period, so the token waits before billing acts. In Swimdraft you can add the timer in the browser editor and the diagram is re-validated live, with the export still opening in Camunda Modeler or any BPMN 2.0 tool.
Related BPMN examples
Customer complaint handling
A customer complaint handling process as a BPMN 2.0 swimlane diagram: logging, investigation, remedy, and a rework loop. View it and download the .bpmn file free.
Product returns
A product returns process in BPMN 2.0: eligibility check, return label, goods inspection, and refund, plus a customer pool with message flows. Free .bpmn download.
Refund request
A refund request process as a BPMN 2.0 diagram: policy check, approval threshold, manager sign off, and payment. View the swimlanes and download the .bpmn free.
Support ticket escalation
A support ticket escalation flow in BPMN 2.0: triage, tier 1 fix, tier 2 diagnosis, and a defect path into engineering. Free .bpmn file download included.
Generate your own version of this diagram
Describe how the process works in your organisation: plain English, meeting notes, a transcript, or a spreadsheet. Swimdraft turns it into a spec-validated BPMN 2.0 diagram you can edit in the browser and export as .bpmn, SVG, or PNG.
Start freeNo credit card required