Skip to content

Reopen rate

How often is a "resolved" ticket not really resolved?

Current value (service case data): 4.1% - ✓ On target. Open the case.

Field Value
Definition Resolved tickets that were reopened at least once, divided by resolved tickets.
Formula count(reopened) / count(resolved)
Unit %
Granularity Ticket; reported monthly by queue and agent group.
Direction Lower is better ↓
Target and thresholds ≤ 5.0% (amber ≤ 8.0%)
Parameters –
Owner Quality Lead (Service)
Source Ticketing system (synthetic generator)
Input table tickets, columns status, reopened
Recommended chart line - Trend next to resolution time to expose a speed-vs-quality trade-off.
Related KPIs First contact resolution (FCR), Resolution time (median)

How to read it

The quality counterweight to every speed KPI. If resolution time improves and reopen rate rises, speed was bought with quality.

Common misreadings

  • Reading it without a time window - reopenings arrive days later, so the last weeks always look better than they are.

Worked example (from the test suite)

ticket_id status first_response_hours resolution_hours sla_target_hours contacts reopened age_days
1 resolved 1.0 10.0 24.0 1 False –
2 resolved 3.0 30.0 24.0 2 False –
3 resolved 0.5 4.0 8.0 1 True –
4 resolved 6.0 50.0 72.0 1 False –
5 open – – 24.0 1 False 9.0

Expected result: 25.00%. Reopened among resolved: only #3. 1 / 4 = 0.25.

This example is asserted in tests/test_formulas.py against the Python function and in tests/test_sql.py against the SQL below.

Implementations

Python function (the single implementation used by the site):

@kpi("reopen_rate")
def reopen_rate(df: pd.DataFrame) -> float:
    r = _resolved(df)
    return safe_ratio(r["reopened"].astype(bool).sum(), len(r))

Reference SQL (tested on SQLite):

SELECT CAST(SUM(CASE WHEN reopened = 1 THEN 1 ELSE 0 END) AS REAL) / COUNT(*)
FROM tickets WHERE status = 'resolved'