SwimdraftPricingSign inStart free

Bug triage BPMN example

Bug triage is the filter between raw bug reports and an engineering backlog worth trusting. Teams map it because without an agreed process, triage becomes whoever shouts loudest: duplicates pile up, vague reports rot unanswered, and genuinely critical defects queue behind cosmetic ones. A mapped flow gives every report a defined route to exactly one outcome.

This model keeps one pool with three lanes: Support, Engineering, and Product owner. Three exclusive gateways test reproducibility, duplication, and severity, and a message catch event models waiting for the reporter to supply missing details before another reproduction attempt. The business rule task for severity is the choice worth noticing: severity assignment follows a decision table, not judgement, so the model uses the task type built for exactly that.

Bug triage: BPMN 2.0 diagram
Bug triage process modelled as a BPMN 2.0 diagram

Standard BPMN 2.0 interchange XML: opens in Camunda Modeler, Signavio, Bizagi, and any other compliant tool.

The process at a glance

Starts when
Bug reported
Ends with
Ticket merged · Hotfix underway · Bug scheduled
Lanes
Support · Engineering · Product owner
Decisions
Reproducible? · Duplicate ticket? · Critical severity?

How to read this diagram

Triage opens when a bug is reported to Support, which tries to reproduce the issue. The gateway "Reproducible?" sends its default No branch to "Request more information", after which the flow waits at the message catch event "Reporter reply received" and loops back for another reproduction attempt. The Yes branch reaches "Duplicate ticket?": on Yes, Support links the report to the existing ticket and the flow ends at "Ticket merged"; the default No branch continues to Engineering.

Engineering assigns a severity level via a business rule task, and the gateway "Critical severity?" splits the remaining work. On the Yes branch an on-call engineer is paged and the flow ends at "Hotfix underway". The default No branch hands the bug to the Product owner, who prioritises it in the backlog, ending at "Bug scheduled". Three distinct end events mean anyone reading the board can see which of the three fates a report met.

BPMN elements used

ElementCountIn this diagram
Start event1Bug reported
End event3Ticket merged, Hotfix underway, Bug scheduled
Intermediate catch event1Reporter reply received
Task2Reproduce reported issue, Link to existing ticket
User task1Prioritise in backlog
Send task2Request more information, Page on-call engineer
Business rule task1Assign severity level
Exclusive gateway3Reproducible?, Duplicate ticket?, Critical severity?
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_bt" name="Bug triage" processRef="Process_pool_bt" />
  </bpmn2:collaboration>
  <bpmn2:process id="Process_pool_bt" isExecutable="false">
    <bpmn2:laneSet id="LaneSet_pool_bt">
      <bpmn2:lane id="lane_bt_sup" name="Support">
        <bpmn2:flowNodeRef>start_bt</bpmn2:flowNodeRef>
        <bpmn2:flowNodeRef>t_bt_repro</bpmn2:flowNodeRef>
        <bpmn2:flowNodeRef>g_bt_repro</bpmn2:flowNodeRef>
        <bpmn2:flowNodeRef>t_bt_info</bpmn2:flowNodeRef>
        <bpmn2:flowNodeRef>ev_bt_reply</bpmn2:flowNodeRef>
        <bpmn2:flowNodeRef>g_bt_dup</bpmn2:flowNodeRef>
        <bpmn2:flowNodeRef>t_bt_link</bpmn2:flowNodeRef>
        <bpmn2:flowNodeRef>end_bt_dup</bpmn2:flowNodeRef>
      </bpmn2:lane>
      <bpmn2:lane id="lane_bt_eng" name="Engineering">
        <bpmn2:flowNodeRef>t_bt_sev</bpmn2:flowNodeRef>
        <bpmn2:flowNodeRef>g_bt_crit</bpmn2:flowNodeRef>
        <bpmn2:flowNodeRef>t_bt_page</bpmn2:flowNodeRef>
        <bpmn2:flowNodeRef>end_bt_hot</bpmn2:flowNodeRef>
      </bpmn2:lane>
      <bpmn2:lane id="lane_bt_po" name="Product owner">
        <bpmn2:flowNodeRef>t_bt_prior</bpmn2:flowNodeRef>
        <bpmn2:flowNodeRef>end_bt_sched</bpmn2:flowNodeRef>
      </bpmn2:lane>
    </bpmn2:laneSet>
    <bpmn2:startEvent id="start_bt" name="Bug reported">
      <bpmn2:outgoing>fbt1</bpmn2:outgoing>
    </bpmn2:startEvent>
    <bpmn2:task id="t_bt_repro" name="Reproduce reported issue">
      <bpmn2:incoming>fbt1</bpmn2:incoming>
      <bpmn2:incoming>fbt6</bpmn2:incoming>
      <bpmn2:outgoing>fbt2</bpmn2:outgoing>
    </bpmn2:task>
    <bpmn2:exclusiveGateway id="g_bt_repro" name="Reproducible?" default="fbt4">
      <bpmn2:incoming>fbt2</bpmn2:incoming>
      <bpmn2:outgoing>fbt3</bpmn2:outgoing>
      <bpmn2:outgoing>fbt4</bpmn2:outgoing>
    </bpmn2:exclusiveGateway>
    <bpmn2:sendTask id="t_bt_info" name="Request more information">
      <bpmn2:incoming>fbt4</bpmn2:incoming>
      <bpmn2:outgoing>fbt5</bpmn2:outgoing>
    </bpmn2:sendTask>
    <bpmn2:intermediateCatchEvent id="ev_bt_reply" name="Reporter reply received">
      <bpmn2:incoming>fbt5</bpmn2:incoming>
      <bpmn2:outgoing>fbt6</bpmn2:outgoing>
      <bpmn2:messageEventDefinition id="ev_bt_reply_def" />
    </bpmn2:intermediateCatchEvent>
    <bpmn2:exclusiveGateway id="g_bt_dup" name="Duplicate ticket?" default="fbt8">
      <bpmn2:incoming>fbt3</bpmn2:incoming>
      <bpmn2:outgoing>fbt7</bpmn2:outgoing>
      <bpmn2:outgoing>fbt8</bpmn2:outgoing>
    </bpmn2:exclusiveGateway>
    <bpmn2:task id="t_bt_link" name="Link to existing ticket">
      <bpmn2:incoming>fbt7</bpmn2:incoming>
      <bpmn2:outgoing>fbt9</bpmn2:outgoing>
    </bpmn2:task>
    <bpmn2:endEvent id="end_bt_dup" name="Ticket merged">
      <bpmn2:incoming>fbt9</bpmn2:incoming>
    </bpmn2:endEvent>
    <bpmn2:businessRuleTask id="t_bt_sev" name="Assign severity level">
      <bpmn2:incoming>fbt8</bpmn2:incoming>
      <bpmn2:outgoing>fbt10</bpmn2:outgoing>
    </bpmn2:businessRuleTask>
    <bpmn2:exclusiveGateway id="g_bt_crit" name="Critical severity?" default="fbt12">
      <bpmn2:incoming>fbt10</bpmn2:incoming>
      <bpmn2:outgoing>fbt11</bpmn2:outgoing>
      <bpmn2:outgoing>fbt12</bpmn2:outgoing>
    </bpmn2:exclusiveGateway>
    <bpmn2:sendTask id="t_bt_page" name="Page on-call engineer">
      <bpmn2:incoming>fbt11</bpmn2:incoming>
      <bpmn2:outgoing>fbt13</bpmn2:outgoing>
    </bpmn2:sendTask>
    <bpmn2:endEvent id="end_bt_hot" name="Hotfix underway">
      <bpmn2:incoming>fbt13</bpmn2:incoming>
    </bpmn2:endEvent>
    <bpmn2:userTask id="t_bt_prior" name="Prioritise in backlog">
      <bpmn2:incoming>fbt12</bpmn2:incoming>
      <bpmn2:outgoing>fbt14</bpmn2:outgoing>
    </bpmn2:userTask>
    <bpmn2:endEvent id="end_bt_sched" name="Bug scheduled">
      <bpmn2:incoming>fbt14</bpmn2:incoming>
    </bpmn2:endEvent>
    <bpmn2:sequenceFlow id="fbt1" sourceRef="start_bt" targetRef="t_bt_repro" />
    <bpmn2:sequenceFlow id="fbt2" sourceRef="t_bt_repro" targetRef="g_bt_repro" />
    <bpmn2:sequenceFlow id="fbt3" name="Yes" sourceRef="g_bt_repro" targetRef="g_bt_dup">
      <bpmn2:conditionExpression xsi:type="bpmn2:tFormalExpression">Yes</bpmn2:conditionExpression>
    </bpmn2:sequenceFlow>
    <bpmn2:sequenceFlow id="fbt4" name="No" sourceRef="g_bt_repro" targetRef="t_bt_info" />
    <bpmn2:sequenceFlow id="fbt5" sourceRef="t_bt_info" targetRef="ev_bt_reply" />
    <bpmn2:sequenceFlow id="fbt6" sourceRef="ev_bt_reply" targetRef="t_bt_repro" />
    <bpmn2:sequenceFlow id="fbt7" name="Yes" sourceRef="g_bt_dup" targetRef="t_bt_link">
      <bpmn2:conditionExpression xsi:type="bpmn2:tFormalExpression">Yes</bpmn2:conditionExpression>
    </bpmn2:sequenceFlow>
    <bpmn2:sequenceFlow id="fbt8" name="No" sourceRef="g_bt_dup" targetRef="t_bt_sev" />
    <bpmn2:sequenceFlow id="fbt9" sourceRef="t_bt_link" targetRef="end_bt_dup" />
    <bpmn2:sequenceFlow id="fbt10" sourceRef="t_bt_sev" targetRef="g_bt_crit" />
    <bpmn2:sequenceFlow id="fbt11" name="Yes" sourceRef="g_bt_crit" targetRef="t_bt_page">
      <bpmn2:conditionExpression xsi:type="bpmn2:tFormalExpression">Yes</bpmn2:conditionExpression>
    </bpmn2:sequenceFlow>
    <bpmn2:sequenceFlow id="fbt12" name="No" sourceRef="g_bt_crit" targetRef="t_bt_prior" />
    <bpmn2:sequenceFlow id="fbt13" sourceRef="t_bt_page" targetRef="end_bt_hot" />
    <bpmn2:sequenceFlow id="fbt14" sourceRef="t_bt_prior" targetRef="end_bt_sched" />
  </bpmn2:process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_1">
    <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Collaboration_1">
      <bpmndi:BPMNShape id="pool_bt_di" bpmnElement="pool_bt" isHorizontal="true">
        <dc:Bounds x="20" y="20" width="1270" height="500" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="lane_bt_sup_di" bpmnElement="lane_bt_sup" isHorizontal="true">
        <dc:Bounds x="50" y="20" width="1240" height="240" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="lane_bt_eng_di" bpmnElement="lane_bt_eng" isHorizontal="true">
        <dc:Bounds x="50" y="260" width="1240" height="130" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="lane_bt_po_di" bpmnElement="lane_bt_po" isHorizontal="true">
        <dc:Bounds x="50" y="390" width="1240" height="130" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="start_bt_di" bpmnElement="start_bt">
        <dc:Bounds x="112" y="59" width="36" height="36" />
        <bpmndi:BPMNLabel><dc:Bounds x="97" y="101" width="66" height="14" /></bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="t_bt_repro_di" bpmnElement="t_bt_repro">
        <dc:Bounds x="230" y="37" width="100" height="80" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="g_bt_repro_di" bpmnElement="g_bt_repro">
        <dc:Bounds x="405" y="52" width="50" height="50" />
        <bpmndi:BPMNLabel><dc:Bounds x="394" y="32" width="73" height="14" /></bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="t_bt_info_di" bpmnElement="t_bt_info">
        <dc:Bounds x="530" y="147" width="100" height="80" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="ev_bt_reply_di" bpmnElement="ev_bt_reply">
        <dc:Bounds x="712" y="169" width="36" height="36" />
        <bpmndi:BPMNLabel><dc:Bounds x="672" y="211" width="117" height="14" /></bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="g_bt_dup_di" bpmnElement="g_bt_dup">
        <dc:Bounds x="555" y="52" width="50" height="50" />
        <bpmndi:BPMNLabel><dc:Bounds x="539" y="32" width="83" height="14" /></bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="t_bt_link_di" bpmnElement="t_bt_link">
        <dc:Bounds x="680" y="37" width="100" height="80" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="end_bt_dup_di" bpmnElement="end_bt_dup">
        <dc:Bounds x="862" y="59" width="36" height="36" />
        <bpmndi:BPMNLabel><dc:Bounds x="844" y="101" width="72" height="14" /></bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="t_bt_sev_di" bpmnElement="t_bt_sev">
        <dc:Bounds x="680" y="277" width="100" height="80" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="g_bt_crit_di" bpmnElement="g_bt_crit">
        <dc:Bounds x="855" y="292" width="50" height="50" />
        <bpmndi:BPMNLabel><dc:Bounds x="839" y="272" width="83" height="14" /></bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="t_bt_page_di" bpmnElement="t_bt_page">
        <dc:Bounds x="980" y="277" width="100" height="80" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="end_bt_hot_di" bpmnElement="end_bt_hot">
        <dc:Bounds x="1162" y="299" width="36" height="36" />
        <bpmndi:BPMNLabel><dc:Bounds x="1140" y="341" width="81" height="14" /></bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="t_bt_prior_di" bpmnElement="t_bt_prior">
        <dc:Bounds x="980" y="407" width="100" height="80" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="end_bt_sched_di" bpmnElement="end_bt_sched">
        <dc:Bounds x="1162" y="429" width="36" height="36" />
        <bpmndi:BPMNLabel><dc:Bounds x="1143" y="471" width="75" height="14" /></bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="fbt1_di" bpmnElement="fbt1">
        <di:waypoint x="148" y="77" />
        <di:waypoint x="230" y="77" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="fbt2_di" bpmnElement="fbt2">
        <di:waypoint x="330" y="77" />
        <di:waypoint x="405" y="77" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="fbt3_di" bpmnElement="fbt3">
        <di:waypoint x="455" y="77" />
        <di:waypoint x="555" y="77" />
        <bpmndi:BPMNLabel><dc:Bounds x="461" y="57" width="21" height="14" /></bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="fbt4_di" bpmnElement="fbt4">
        <di:waypoint x="455" y="77" />
        <di:waypoint x="510" y="77" />
        <di:waypoint x="510" y="187" />
        <di:waypoint x="530" y="187" />
        <bpmndi:BPMNLabel><dc:Bounds x="461" y="83" width="17" height="14" /></bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="fbt5_di" bpmnElement="fbt5">
        <di:waypoint x="630" y="187" />
        <di:waypoint x="712" y="187" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="fbt6_di" bpmnElement="fbt6">
        <di:waypoint x="748" y="187" />
        <di:waypoint x="810" y="187" />
        <di:waypoint x="810" y="242" />
        <di:waypoint x="210" y="242" />
        <di:waypoint x="210" y="77" />
        <di:waypoint x="230" y="77" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="fbt7_di" bpmnElement="fbt7">
        <di:waypoint x="605" y="77" />
        <di:waypoint x="680" y="77" />
        <bpmndi:BPMNLabel><dc:Bounds x="611" y="57" width="21" height="14" /></bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="fbt8_di" bpmnElement="fbt8">
        <di:waypoint x="605" y="77" />
        <di:waypoint x="660" y="77" />
        <di:waypoint x="660" y="317" />
        <di:waypoint x="680" y="317" />
        <bpmndi:BPMNLabel><dc:Bounds x="611" y="83" width="17" height="14" /></bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="fbt9_di" bpmnElement="fbt9">
        <di:waypoint x="780" y="77" />
        <di:waypoint x="862" y="77" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="fbt10_di" bpmnElement="fbt10">
        <di:waypoint x="780" y="317" />
        <di:waypoint x="855" y="317" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="fbt11_di" bpmnElement="fbt11">
        <di:waypoint x="905" y="317" />
        <di:waypoint x="980" y="317" />
        <bpmndi:BPMNLabel><dc:Bounds x="911" y="297" width="21" height="14" /></bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="fbt12_di" bpmnElement="fbt12">
        <di:waypoint x="905" y="317" />
        <di:waypoint x="960" y="317" />
        <di:waypoint x="960" y="447" />
        <di:waypoint x="980" y="447" />
        <bpmndi:BPMNLabel><dc:Bounds x="911" y="323" width="17" height="14" /></bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="fbt13_di" bpmnElement="fbt13">
        <di:waypoint x="1080" y="317" />
        <di:waypoint x="1162" y="317" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="fbt14_di" bpmnElement="fbt14">
        <di:waypoint x="1080" y="447" />
        <di:waypoint x="1162" y="447" />
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</bpmn2:definitions>

Frequently asked questions

Why is severity assignment a business rule task rather than a user task?

Because good triage teams score severity against a published matrix: data loss, users affected, workaround available. A business rule task signals that the decision follows a defined table rather than individual judgement. If your team debates severity case by case in a meeting, a user task would be the more honest choice.

Why does the information request loop through a message event?

The process can do nothing until the reporter answers, and that pause is external to the organisation running triage. An intermediate message catch event models the wait precisely, and the loop back to "Reproduce reported issue" shows that fresh details always trigger another attempt rather than skipping straight to severity.

Where would a timer attach for reports that never get a reply?

Race the "Reporter reply received" event against a timer intermediate event, for example seven days, with the timer branch flowing to a "Close as stale" task and its own end event. That stops abandoned reports from waiting forever, and the end event name makes the stale outcome countable in reporting.

Related BPMN examples

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 free

No credit card required