DORA Metrics
The four DORA keys on one screen, each classified Elite→Low against its trend, with the metric holding the team back.
Platform · DORA four keys
2 / 4
DORA metrics at Elite
2 of 4 DORA metrics at Elite; Change fail rate (Low) is the gap.
Deploy frequency
14 / wk
Lead time
18h
Change fail rate
18%
Time to restore
5.5h
| Metric | Value | Band |
|---|---|---|
| Deploy frequency | 14 / wk | Elite |
| Lead time | 18h | Elite |
| Change fail rate | 18% | Low |
| Time to restore | 5.5h | High |
Platform metrics · synced from Jenkins + PagerDuty hourly
Demo data is illustrative. Replace with your own typed data prop.
How it computes
Four DORA metrics each classified Elite / High / Medium / Low against the published 2023 thresholds.
deploy/wk: Elite ≥7 · lead-time h: Elite <24 · change-fail %: Elite ≤5 · MTTR h: Elite <1Assumptions
- Each metric is classified independently.
- Band boundaries are the 2023 DORA report definitions.
Honest about
- Thresholds are the published DORA cutoffs, cited — not bands we invented.
- The headline "weakest metric" is the lowest-ranked band (Elite=3 … Low=0), so the gap is surfaced, not the average.
- Sparkline trends are min/max normalized for shape only — they are not z-scored or forecast.
Reference: Google Cloud — 2023 State of DevOps (DORA) report
Use it with your data
Data contract
Passed via the data prop — an object: validated at runtime, so a bad shape degrades to the error state rather than crashing.
| Field | Type | Required |
|---|---|---|
| deployFreqPerWeek | number | yes |
| leadTimeHours | number | yes |
| changeFailPct | number | yes |
| mttrHours | number | yes |
| trends | object | yes |
Static props
import { EngDoraMetrics } from "@/components/blocks/eng-dora-metrics/eng-dora-metrics";
<EngDoraMetrics data={myData} />Client fetch (SWR)
const { data, isLoading, error } = useSWR("/api/metric", fetcher);
// route isLoading/error through <ChartStates>, then:
<EngDoraMetrics data={data} />Server component (RSC)
const data = await fetch(url, {
next: { revalidate: 3600 },
}).then((r) => r.json());
<EngDoraMetrics data={data} />Map arbitrary rows
import { mapRows } from "@/lib/sextant/column-map";
const out = mapRows(rows, { /* contractKey: "yourColumn" */ }, dataSchema);
if (out.ok) <EngDoraMetrics data={out.data} />;Make it yours
Every customization below is an optional prop — omit them all and you get the defaults shown above. Recolor, reformat, restyle, or drop the card chrome without forking the component.
Recolor or rename a series (elite, low)
<EngDoraMetrics
series={{ elite: { color: "var(--chart-3)", label: "…" } }}
/>Replace or hide the narrative
<EngDoraMetrics narrative="Your own one-liner." />
// …or hide it entirely:
<EngDoraMetrics narrative={false} />Restyle any region
<EngDoraMetrics
className="max-w-xl"
classNames={{ body: "bg-muted/20" }}
/>