Customer complaint handling BPMN example
Complaint handling is where a customer relationship is either repaired or lost for good. Teams map the process because regulators, quality standards such as ISO 10002, and plain common sense all demand a consistent route from first contact to resolution. In practice the process goes wrong at the handoff: the front line logs a complaint, passes it on, and nobody owns it until the customer chases.
This example models complaint handling as one pool with three lanes: Front line support, Complaints team, and Quality assurance. Two exclusive gateways shape the flow, one for first contact resolution and one for whether the customer accepts the proposed remedy. The modelling choice worth noticing is the rework loop: a rejected remedy sends the token back to investigation rather than to a dead end.
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
Everything begins in the Front line support lane when a complaint is received. The agent logs the complaint details, then the gateway "Resolved at first contact?" splits the flow. On the Yes branch the agent confirms the outcome with the customer and the process ends at "Complaint closed". The No branch, marked as the default flow, drops into the Complaints team lane, where a case handler is assigned.
From there the handler investigates the complaint and proposes a remedy. The second gateway, "Remedy accepted?", tests the customer response: Yes moves to the Quality assurance lane, where the root cause is recorded before the "Complaint resolved" end event; No, the default flow, loops back to the investigation task so the handler can try again. The loop keeps every token on a path to an end event while modelling the reality that first remedies are often refused.
BPMN elements used
| Element | Count | In this diagram |
|---|---|---|
| Start event | 1 | Complaint received |
| End event | 2 | Complaint closed, Complaint resolved |
| Task | 3 | Assign case handler, Propose remedy, Record root cause |
| User task | 2 | Log complaint details, Investigate complaint |
| Send task | 1 | Confirm outcome with customer |
| Exclusive gateway | 2 | Resolved at first contact?, Remedy accepted? |
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_cc" name="Complaint handling" processRef="Process_pool_cc" />
</bpmn2:collaboration>
<bpmn2:process id="Process_pool_cc" isExecutable="false">
<bpmn2:laneSet id="LaneSet_pool_cc">
<bpmn2:lane id="lane_cc_front" name="Front line support">
<bpmn2:flowNodeRef>start_cc</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>t_cc_log</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>g_cc_first</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>t_cc_confirm</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>end_cc_closed</bpmn2:flowNodeRef>
</bpmn2:lane>
<bpmn2:lane id="lane_cc_team" name="Complaints team">
<bpmn2:flowNodeRef>t_cc_assign</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>t_cc_invest</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>t_cc_remedy</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>g_cc_accept</bpmn2:flowNodeRef>
</bpmn2:lane>
<bpmn2:lane id="lane_cc_qa" name="Quality assurance">
<bpmn2:flowNodeRef>t_cc_record</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>end_cc_resolved</bpmn2:flowNodeRef>
</bpmn2:lane>
</bpmn2:laneSet>
<bpmn2:startEvent id="start_cc" name="Complaint received">
<bpmn2:outgoing>f_cc1</bpmn2:outgoing>
</bpmn2:startEvent>
<bpmn2:userTask id="t_cc_log" name="Log complaint details">
<bpmn2:incoming>f_cc1</bpmn2:incoming>
<bpmn2:outgoing>f_cc2</bpmn2:outgoing>
</bpmn2:userTask>
<bpmn2:exclusiveGateway id="g_cc_first" name="Resolved at first contact?" default="f_cc4">
<bpmn2:incoming>f_cc2</bpmn2:incoming>
<bpmn2:outgoing>f_cc3</bpmn2:outgoing>
<bpmn2:outgoing>f_cc4</bpmn2:outgoing>
</bpmn2:exclusiveGateway>
<bpmn2:sendTask id="t_cc_confirm" name="Confirm outcome with customer">
<bpmn2:incoming>f_cc3</bpmn2:incoming>
<bpmn2:outgoing>f_cc5</bpmn2:outgoing>
</bpmn2:sendTask>
<bpmn2:endEvent id="end_cc_closed" name="Complaint closed">
<bpmn2:incoming>f_cc5</bpmn2:incoming>
</bpmn2:endEvent>
<bpmn2:task id="t_cc_assign" name="Assign case handler">
<bpmn2:incoming>f_cc4</bpmn2:incoming>
<bpmn2:outgoing>f_cc6</bpmn2:outgoing>
</bpmn2:task>
<bpmn2:userTask id="t_cc_invest" name="Investigate complaint">
<bpmn2:incoming>f_cc6</bpmn2:incoming>
<bpmn2:incoming>f_cc10</bpmn2:incoming>
<bpmn2:outgoing>f_cc7</bpmn2:outgoing>
</bpmn2:userTask>
<bpmn2:task id="t_cc_remedy" name="Propose remedy">
<bpmn2:incoming>f_cc7</bpmn2:incoming>
<bpmn2:outgoing>f_cc8</bpmn2:outgoing>
</bpmn2:task>
<bpmn2:exclusiveGateway id="g_cc_accept" name="Remedy accepted?" default="f_cc10">
<bpmn2:incoming>f_cc8</bpmn2:incoming>
<bpmn2:outgoing>f_cc9</bpmn2:outgoing>
<bpmn2:outgoing>f_cc10</bpmn2:outgoing>
</bpmn2:exclusiveGateway>
<bpmn2:task id="t_cc_record" name="Record root cause">
<bpmn2:incoming>f_cc9</bpmn2:incoming>
<bpmn2:outgoing>f_cc11</bpmn2:outgoing>
</bpmn2:task>
<bpmn2:endEvent id="end_cc_resolved" name="Complaint resolved">
<bpmn2:incoming>f_cc11</bpmn2:incoming>
</bpmn2:endEvent>
<bpmn2:sequenceFlow id="f_cc1" sourceRef="start_cc" targetRef="t_cc_log" />
<bpmn2:sequenceFlow id="f_cc2" sourceRef="t_cc_log" targetRef="g_cc_first" />
<bpmn2:sequenceFlow id="f_cc3" name="Yes" sourceRef="g_cc_first" targetRef="t_cc_confirm">
<bpmn2:conditionExpression xsi:type="bpmn2:tFormalExpression">Yes</bpmn2:conditionExpression>
</bpmn2:sequenceFlow>
<bpmn2:sequenceFlow id="f_cc4" name="No" sourceRef="g_cc_first" targetRef="t_cc_assign" />
<bpmn2:sequenceFlow id="f_cc5" sourceRef="t_cc_confirm" targetRef="end_cc_closed" />
<bpmn2:sequenceFlow id="f_cc6" sourceRef="t_cc_assign" targetRef="t_cc_invest" />
<bpmn2:sequenceFlow id="f_cc7" sourceRef="t_cc_invest" targetRef="t_cc_remedy" />
<bpmn2:sequenceFlow id="f_cc8" sourceRef="t_cc_remedy" targetRef="g_cc_accept" />
<bpmn2:sequenceFlow id="f_cc9" name="Yes" sourceRef="g_cc_accept" targetRef="t_cc_record">
<bpmn2:conditionExpression xsi:type="bpmn2:tFormalExpression">Yes</bpmn2:conditionExpression>
</bpmn2:sequenceFlow>
<bpmn2:sequenceFlow id="f_cc10" name="No" sourceRef="g_cc_accept" targetRef="t_cc_invest" />
<bpmn2:sequenceFlow id="f_cc11" sourceRef="t_cc_record" targetRef="end_cc_resolved" />
</bpmn2:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Collaboration_1">
<bpmndi:BPMNShape id="pool_cc_di" bpmnElement="pool_cc" isHorizontal="true">
<dc:Bounds x="20" y="20" width="1420" height="390" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="lane_cc_front_di" bpmnElement="lane_cc_front" isHorizontal="true">
<dc:Bounds x="50" y="20" width="1390" height="130" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="lane_cc_team_di" bpmnElement="lane_cc_team" isHorizontal="true">
<dc:Bounds x="50" y="150" width="1390" height="130" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="lane_cc_qa_di" bpmnElement="lane_cc_qa" isHorizontal="true">
<dc:Bounds x="50" y="280" width="1390" height="130" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="start_cc_di" bpmnElement="start_cc">
<dc:Bounds x="112" y="59" width="36" height="36" />
<bpmndi:BPMNLabel><dc:Bounds x="82" y="101" width="97" height="14" /></bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="t_cc_log_di" bpmnElement="t_cc_log">
<dc:Bounds x="230" y="37" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="g_cc_first_di" bpmnElement="g_cc_first">
<dc:Bounds x="405" y="52" width="50" height="50" />
<bpmndi:BPMNLabel><dc:Bounds x="367" y="32" width="126" height="14" /></bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="t_cc_confirm_di" bpmnElement="t_cc_confirm">
<dc:Bounds x="530" y="37" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="end_cc_closed_di" bpmnElement="end_cc_closed">
<dc:Bounds x="712" y="59" width="36" height="36" />
<bpmndi:BPMNLabel><dc:Bounds x="687" y="101" width="87" height="14" /></bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="t_cc_assign_di" bpmnElement="t_cc_assign">
<dc:Bounds x="530" y="167" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="t_cc_invest_di" bpmnElement="t_cc_invest">
<dc:Bounds x="680" y="167" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="t_cc_remedy_di" bpmnElement="t_cc_remedy">
<dc:Bounds x="830" y="167" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="g_cc_accept_di" bpmnElement="g_cc_accept">
<dc:Bounds x="1005" y="182" width="50" height="50" />
<bpmndi:BPMNLabel><dc:Bounds x="982" y="162" width="97" height="14" /></bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="t_cc_record_di" bpmnElement="t_cc_record">
<dc:Bounds x="1130" y="297" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="end_cc_resolved_di" bpmnElement="end_cc_resolved">
<dc:Bounds x="1312" y="319" width="36" height="36" />
<bpmndi:BPMNLabel><dc:Bounds x="1282" y="361" width="97" height="14" /></bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="f_cc1_di" bpmnElement="f_cc1">
<di:waypoint x="148" y="77" />
<di:waypoint x="230" y="77" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="f_cc2_di" bpmnElement="f_cc2">
<di:waypoint x="330" y="77" />
<di:waypoint x="405" y="77" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="f_cc3_di" bpmnElement="f_cc3">
<di:waypoint x="455" y="77" />
<di:waypoint x="530" y="77" />
<bpmndi:BPMNLabel><dc:Bounds x="461" y="57" width="21" height="14" /></bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="f_cc4_di" bpmnElement="f_cc4">
<di:waypoint x="455" y="77" />
<di:waypoint x="510" y="77" />
<di:waypoint x="510" y="207" />
<di:waypoint x="530" y="207" />
<bpmndi:BPMNLabel><dc:Bounds x="461" y="83" width="17" height="14" /></bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="f_cc5_di" bpmnElement="f_cc5">
<di:waypoint x="630" y="77" />
<di:waypoint x="712" y="77" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="f_cc6_di" bpmnElement="f_cc6">
<di:waypoint x="630" y="207" />
<di:waypoint x="680" y="207" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="f_cc7_di" bpmnElement="f_cc7">
<di:waypoint x="780" y="207" />
<di:waypoint x="830" y="207" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="f_cc8_di" bpmnElement="f_cc8">
<di:waypoint x="930" y="207" />
<di:waypoint x="1005" y="207" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="f_cc9_di" bpmnElement="f_cc9">
<di:waypoint x="1055" y="207" />
<di:waypoint x="1110" y="207" />
<di:waypoint x="1110" y="337" />
<di:waypoint x="1130" y="337" />
<bpmndi:BPMNLabel><dc:Bounds x="1061" y="187" width="21" height="14" /></bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="f_cc10_di" bpmnElement="f_cc10">
<di:waypoint x="1055" y="207" />
<di:waypoint x="1110" y="207" />
<di:waypoint x="1110" y="262" />
<di:waypoint x="660" y="262" />
<di:waypoint x="660" y="207" />
<di:waypoint x="680" y="207" />
<bpmndi:BPMNLabel><dc:Bounds x="1061" y="213" width="17" height="14" /></bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="f_cc11_di" bpmnElement="f_cc11">
<di:waypoint x="1230" y="337" />
<di:waypoint x="1312" y="337" />
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn2:definitions>Frequently asked questions
Why does the rejected remedy loop back to investigation instead of ending?
Ending the process on a rejected remedy would model giving up on the customer, which is rarely the real procedure. Looping back to the investigation task keeps the model honest and keeps every node on a path from start to end. If your organisation caps the number of attempts, add a counter check or an escalation branch after the loop.
Should Quality assurance be a separate pool rather than a lane?
No, because quality assurance works inside the same organisation and on the same process instance as the other teams. Lanes show internal responsibility within one pool; pools are reserved for independent participants that communicate by message, such as the customer or an ombudsman service reviewing the case.
Where would an escalation or timer attach in this model?
The natural spot is the investigation task. A boundary timer event on "Investigate complaint" could route cases that exceed a service level, say ten working days, to a manager. This example keeps the flow to plain sequence flows for readability, so adding the timer is the obvious first extension for a regulated environment.
Related BPMN examples
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.
Warranty claim
A warranty claim process as a BPMN 2.0 diagram: registration, a document chase loop, fault assessment, and repair or replace routing. Free .bpmn file download.
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