Skip to content

Mean time to repair (MTTR)

Once an asset fails, how long until it runs again?

Current value (maintenance case data): 5.3 h - ! Watch. Open the case.

Field Value
Definition Mean repair hours (failure to return to service) over corrective work orders.
Formula mean(repair_hours) for wo_type = corrective
Unit hours
Granularity Corrective work order; reported monthly by asset and failure mode.
Direction Lower is better ↓
Target and thresholds ≤ 4.0 h (amber ≤ 6.0 h)
Parameters –
Owner Maintenance Supervisor
Source Work-order generator (synthetic)
Input table work_orders, columns wo_type, repair_hours
Recommended chart boxplot - Distribution per failure mode shows whether the mean is driven by a tail.
Related KPIs Mean time between failures (MTBF), Availability

How to read it

Kept as a mean so that availability = MTBF / (MTBF + MTTR) holds. Because repair times are right-skewed, always look at the median and the longest repairs: waiting for spare parts usually lives in the tail.

Common misreadings

  • Mean vs median - a few repairs waiting for parts can double the mean while the typical repair is unchanged.
  • Repair time is not response time; mixing "time to arrive" and "time to fix" hides where the delay is.

Worked example (from the test suite)

wo_type repair_hours
corrective 2.0
corrective 3.0
corrective 10.0
preventive 1.0

Expected result: 5.00 h. Corrective only: (2 + 3 + 10) / 3 = 5.0 h. The median would be 3.0 h - one long repair drives the mean.

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("mttr")
def mttr(df: pd.DataFrame) -> float:
    repairs = df.loc[df["wo_type"].eq("corrective"), "repair_hours"].dropna()
    return float(repairs.mean()) if len(repairs) else float("nan")

Reference SQL (tested on SQLite):

SELECT AVG(repair_hours) FROM work_orders WHERE wo_type = 'corrective'