Delivery performance — the four DORA keys, 27.64 days
Snapshot taken — build-time, not live
Deployment frequency
81.3
successful deployments per day
Eliten = 2,248
How this is derived
Successful runs of deploy-class pipelines, divided by the observed window. Deploy-class is imported from the estate's own pipeline-metrics collector, not restated here: pipelines that put something on a host, with guard, lint and validation pipelines excluded.
Lead time for changes
6.3
minutes, median (p90 20.6)
Eliten = 2,248
How this is derived
CI trigger to deployment complete, for successful CI-triggered deploy-class runs. The trigger fires within seconds of the push, so this is commit-to-live to within webhook latency. It is stated as that rather than dressed up as exact: resolving each commit's author date misreports a rebase or an old branch merge far more badly than this does.
Change failure rate
5.2
% of deployments that failed
Highn = 2,372
How this is derived
Deploy-class runs that ended `failed`, over those that ended `failed` or `succeeded`. This is the rate at which a change failed to reach production, which is not identical to DORA's 'caused a degradation in service' — a red gate usually stops the change before it lands. It is reported as what it measures rather than relabelled as what it resembles.
Failed-deployment recovery time
26.8
minutes, median (p90 403.4)
Eliten = 92
How this is derived
For each failed deploy-class run, the wall-clock until that same pipeline next succeeded. Failures still unrecovered at the end of the window are counted separately (2 in this window) and are not folded in as zero.
Computed from 4,669 completed Azure DevOps pipeline runs over the 28-day window ending , of which 2,377 were deploy-class. The deploy classification is not restated here — it is imported from ado_pipeline_metrics.py (ADR-0331), the estate's single pipeline-metrics collector, so the public figures and the internal queue-time SLO can never quietly disagree about which pipelines count as a deployment. Elite / High / Medium / Low are the DORA State of DevOps report's own thresholds, not thresholds derived from this estate. 2 failures were still unrecovered at the end of the window and are excluded from the recovery-time median rather than folded in as zero.
A DORA figure with no stated definition is unfalsifiable. “Deployment frequency: eighty a day” can
mean almost anything depending on what counts as a deployment — every pipeline run, every
successful run, every run of a pipeline that touches a host, every distinct change — and a reader
has no way to distinguish a measured number from a flattering one.
So each tile shows four things, not one: the value, the sample count behind it, the performance
band from the DORA report’s own thresholds, and an expandable derivation stating exactly which
runs were counted.
The change failure rate tile is the sharp one and is worth reading closely. What is measured
is the proportion of deployments that failed to reach production — a red gate, a failed apply.
That is not the DORA definition, which is the proportion of changes that cause a degradation
in service requiring remediation. In this estate most failures are caught by a gate before
anything lands, which makes the measured number both real and not the thing DORA names. It is
reported as what it measures rather than relabelled as what it resembles, because borrowing the
more flattering definition is the easiest possible way to publish a false number.
Elite, High, Medium and Low come from the DORA State of DevOps report’s published thresholds.
They are not derived from anything measured about this estate. A threshold lifted from an external
reference and presented as a local finding produces a control that looks canonical, reviews
cleanly, and cannot work — it is one of the named failure classes carried into every session here.
Stating the provenance is the whole mitigation.
The estate already has a single collector polling the build API for queue and run timing; it feeds
the internal CI queue-time objective and its error budget. The rule attached to it is explicit:
do not build a second collector, because two pollers against one API drift apart and the
disagreement is discovered during an incident.
This panel obeys that literally. It writes no series, no counters and no state — it is a read-only
report — and, more importantly, it does not restate the estate’s definitions. The deploy
classification is imported from that collector at build time, so a change to what counts as a
deployment moves this public figure with it rather than leaving a stale copy to rot. One
declaration, two consumers.
Twenty-eight days, matching the internal objective’s window, walked backwards through the build
API in bounded slices. Each slice asserts it came back under the API’s result cap: a full page
means the slice was truncated, so the run set would be incomplete, and the build fails rather than
quietly measuring a fraction of the window and reporting it as the whole thing.
A run missing a timestamp is skipped, never defaulted to zero — a cancelled run that never
started would otherwise contribute a zero-second lead time and silently improve every figure.
Failures still unrecovered at the end of the window are counted separately rather than folded into
the recovery median as zero. That is the honest treatment of right-censored data and it is stated
on the panel.
High deployment frequency and short lead time here are partly a property of scale: this is a
homelab, changes are small, and there is no change-approval board between a commit and a
production apply. That is worth saying out loud, because the same numbers in a regulated
enterprise would mean something quite different and would have been much harder to earn.
What the numbers do say is that the path from a commit to a running change is fully automated,
gated, and measured — and that the measurement is derived from the system of record rather than
from anyone’s impression of it. The story of how the CI pool got to these figures, and what the
baseline was before, is in queue time is a CI pool’s
latency.