Metric · DORA

What is MTTR, and how do you measure it in Metabase?

MTTR — mean time to recovery, which DORA calls time to restore service — is how long it takes to recover from a production failure. It's a DORA stability metric, the recovery half of change failure rate. Measure it in Metabase from incident timestamps, joined where possible to the GitHub or GitLab deploy that triggered the failure.

TL;DR — Incident started_atresolved_at, reported as a median (and p90), not a mean. Despite the name, don't use the average — recovery times are heavily skewed.

What MTTR measures

It measures recovery speed: from when a production incident starts to when service is restored. Low MTTR means failures are detected and resolved fast, so you can deploy frequently without large blast radius. Report median + p90; a single multi-day outage will wreck a mean.

What data does it need?

  • An incidents table: started_at, resolved_at, severity, environment, and optionally deployment_id.
  • Source: PagerDuty, Opsgenie, incident.io, Statuspage, or GitHub/GitLab issues labeled incident with open/close timestamps.

SQL patterns

Median + p90 time to restore by monthPostgreSQL
SELECT
  date_trunc('month', started_at) AS month,
  COUNT(*) AS incidents,
  percentile_cont(0.5) WITHIN GROUP (
    ORDER BY EXTRACT(EPOCH FROM (resolved_at - started_at)) / 3600
  ) AS median_restore_hours,
  percentile_cont(0.9) WITHIN GROUP (
    ORDER BY EXTRACT(EPOCH FROM (resolved_at - started_at)) / 3600
  ) AS p90_restore_hours
FROM incidents
WHERE resolved_at IS NOT NULL
  AND environment = 'production'
GROUP BY 1
ORDER BY 1;
By severity (trailing 90 days)PostgreSQL
SELECT
  severity,
  COUNT(*) AS incidents,
  percentile_cont(0.5) WITHIN GROUP (
    ORDER BY EXTRACT(EPOCH FROM (resolved_at - started_at)) / 60
  ) AS median_restore_minutes
FROM incidents
WHERE resolved_at IS NOT NULL
  AND started_at >= CURRENT_DATE - INTERVAL '90 days'
GROUP BY 1
ORDER BY median_restore_minutes DESC;

Pitfalls

Reporting the mean.→ Despite the "M" in MTTR, use the median (and p90); one long outage skews the average.
Wrong start time.→ Use detection/start time, not the time someone got around to opening a ticket.
Mixing incident types.→ Segment by severity; a Sev-1 outage and a minor blip shouldn't be averaged together.
Counting unresolved incidents.→ Exclude open incidents (resolved_at IS NULL) from the duration math.

Where this metric applies

Metrics

Integrations

Dashboards

FAQ

What is MTTR?
MTTR — mean time to recovery, which DORA calls time to restore service — measures how long it takes to recover from a production failure, from when an incident starts to when service is restored. It is one of the two DORA stability metrics alongside change failure rate. Low MTTR means failures are detected and resolved fast, so teams can keep deployment frequency high without a large blast radius. See the DORA overview for how the four keys fit together.
Is MTTR the same as DORA's time to restore service?
They're used interchangeably. DORA's official label is time to restore service; MTTR (mean time to recovery) is the common shorthand for the same measurement — failure start to service restored. Whatever you call it, report it as a median with p90 rather than a mean, and read it next to change failure rate so recovery speed and failure rate stay paired. The DORA metrics overview covers the full framework and performance bands.
What is the difference between MTTR and MTTA?
MTTA (mean time to acknowledge) measures how fast a human responds: incident created to first acknowledgment. MTTR measures how fast service recovers: failure start to resolution, including diagnosis and remediation. MTTA is the on-call responsiveness half; MTTR is the end-to-end recovery number. Track both on an incident response dashboard — a rising MTTR with a flat MTTA points at remediation, not paging, as the bottleneck.
Mean or median?
Median, plus p90. Recovery times are right-skewed — most incidents resolve quickly while a few run for days — so the mean overstates typical recovery, and one bad outage swings the whole trend. Use percentile_cont(0.5) and percentile_cont(0.9) as in the SQL patterns above, segment by severity, and exclude open incidents (resolved_at IS NULL) from the duration math. The same right-skew applies to MTTA and lead time for changes.
Where do start and end times come from?
From your incident tool — PagerDuty, Opsgenie, or incident.io — or from GitHub/GitLab issues labeled incident with open and close timestamps. Use detection or failure start time as the start, not when someone got around to opening a ticket, and service restored as the end. Joining a deployment_id from GitHub or GitLab onto each incident also unlocks change failure rate from the same table.