Everything in this track, from small pull requests to pipelines to GitOps, is supposed to make delivery faster and safer. How do you know whether it is working? The DORA research programme has studied software teams for over a decade and identified a small set of metrics that reliably distinguish high-performing teams, and that predict organisational outcomes. This module explains what they measure, how to compute them from data you already have, and how to improve them without turning them into targets that people game.
- Define the four key DORA metrics and explain why throughput and stability rise together
- Compute each metric from deployment and incident records you already have
- Diagnose which constraint a poor metric points at, and choose the right improvement
- Use the metrics to guide a team's improvement without turning them into individual targets
- Recognise common ways the metrics are gamed or misread
The four keys
DORA stands for DevOps Research and Assessment, the group behind the annual State of DevOps reports and the book Accelerate. Its central finding is a set of four metrics, in two pairs.
| Metric | Measures | Question it answers |
|---|---|---|
| Deployment frequency | Throughput | How often do we release to production? |
| Lead time for changes | Throughput | How long from a commit to that commit running in production? |
| Change failure rate | Stability | What fraction of deployments cause a failure that needs remediation? |
| Time to restore service | Stability | When a deployment fails, how long until service is restored? |
The research's most important result contradicts a deeply held intuition: speed and stability are not a trade-off. The teams that deploy most often are also the ones with the lowest failure rates and fastest recovery. The cause runs in one direction. Deploying often forces changes to be small, and small changes are easy to review, easy to test, unlikely to fail, and quick to diagnose and revert when they do. Large, infrequent releases bundle hundreds of changes, so something always breaks, and finding it takes a long time.
Recent reports have refined the stability measures, renaming time to restore as failed deployment recovery time and adding a measure of unplanned rework. They have also discussed reliability, meaning whether a service meets its operational targets, as a related outcome. That last one is the subject of the SRE track. The exact benchmark figures shift from year to year, so read the current report for them and do not memorise numbers.
The metrics describe a team and a service, not individual people. Used per person they measure nothing meaningful and cause real harm.
Computing them from data you already have
You need only two kinds of event. A deployment record has a service, a timestamp, the commit that was deployed and, ideally, whether it later needed remediation. An incident record has a start time, a restore time and, where known, the deployment that caused it. Your pipeline and your incident tool already produce both.
deployment frequency = production deployments / time period
lead time for changes = median( deploy time - commit time )
over every commit included in each deployment
change failure rate = deployments needing remediation / total deployments
(remediation = rollback, hotfix, forward fix, patch)
time to restore = median( restored time - failure start time )
over failures caused by a change-- deployment frequency: deployments per week, per service
SELECT service, date_trunc('week', deployed_at) AS week, count(*) AS deployments
FROM deployments
WHERE environment = 'production'
GROUP BY service, week
ORDER BY week;
-- lead time for changes: median hours from commit to production
SELECT d.service,
percentile_cont(0.5) WITHIN GROUP (
ORDER BY extract(epoch FROM d.deployed_at - c.committed_at) / 3600
) AS median_lead_time_hours
FROM deployments d
JOIN deployment_commits c ON c.deployment_id = d.id
WHERE d.environment = 'production'
GROUP BY d.service;
-- change failure rate
SELECT service,
avg(CASE WHEN caused_failure THEN 1.0 ELSE 0.0 END) AS change_failure_rate
FROM deployments
WHERE environment = 'production'
GROUP BY service;- Use the median, not the mean. One change that sat for three weeks, or one twelve-hour outage, distorts an average and hides the typical experience. Track a high percentile alongside it to see the bad cases.
- Measure lead time from commit, not from when the ticket was created. The time before coding starts is product and planning work, which is a different and much noisier thing.
- Be strict and consistent about what counts as a failure: a deployment that led to degraded service for users and required remediation. A failed pipeline run that never reached production is not a change failure; it is the pipeline doing its job.
- Start with a spreadsheet if necessary. A rough number tracked consistently every month is far more useful than a perfect dashboard that is never built.
Instrumenting the pipeline
The most reliable source for deployment data is the pipeline itself. Emit one event at the end of every production deploy. With Git, you can list exactly which commits are new in this deployment by comparing with the previously deployed commit.
#!/usr/bin/env bash
set -euo pipefail
service="orders"
new_sha="$(git rev-parse HEAD)"
prev_sha="$(cat .last-deployed-sha)" # recorded by the previous deployment
deployed_at="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
# every commit that is new in this deployment, with its commit timestamp
git log --format='%H %cI' "${prev_sha}..${new_sha}" > commits.txt
jq -n --arg service "$service" --arg sha "$new_sha" --arg at "$deployed_at" \
--rawfile commits commits.txt \
'{service: $service, sha: $sha, deployed_at: $at, commits: ($commits | split("\n") | map(select(. != "")))}' \
> deployment-event.json
curl -fsS -X POST -H 'Content-Type: application/json' \
--data @deployment-event.json "$METRICS_ENDPOINT"
echo "$new_sha" > .last-deployed-shaTag each deployment with the commit SHA, as the artifacts module recommended, and the link from a production incident back to the change that caused it becomes a lookup instead of an investigation. Several open-source projects and most delivery platforms can compute the four keys from your Git host and incident tool directly, which is worth evaluating before you build your own.
Reading the numbers: which constraint is it?
A metric tells you where to look, not what to do. Break lead time into its stages to find where a change spends its life. In most teams the great majority of lead time is waiting, not working.
| Symptom | Likely constraint | What helps |
|---|---|---|
| Long wait for first review | Large PRs, review is nobody's priority | Smaller PRs, a team norm for review time, pairing |
| Long pipeline stage | Slow or serial tests, no caching | Caching, parallel jobs, a faster test pyramid |
| Merged code waits days to ship | Manual release process, release windows, change board | Automated deploys, trunk-based development, feature flags |
| Low deployment frequency | Deploys are painful or risky, so they are batched | Make deploys boring: automate, canary, fast rollback |
| High change failure rate | Large changes, weak tests, staging unlike production | Smaller changes, better test coverage, progressive delivery |
| Long time to restore | Slow detection, no quick rollback, unclear ownership | Alerting on symptoms, one-command rollback, runbooks, on-call |
DORA's research also identifies the capabilities that drive the metrics. The technical ones are the contents of this track: version control for everything, trunk-based development, continuous integration, test automation, deployment automation, loosely coupled architecture, and monitoring. The cultural ones matter just as much: a generative, blameless culture, small batch sizes, and limited work in progress. A heavyweight external change-approval board, notably, was found to slow delivery without improving stability.
Work on one constraint at a time, and re-measure. Improving a stage that is not the bottleneck changes nothing: a build that is five minutes faster is invisible if changes then wait four days for a release window.
Using the metrics without abusing them
Goodhart's law says that when a measure becomes a target, it ceases to be a good measure. Every one of the four keys can be gamed, and will be, if people are rewarded or punished for the number.
- Deployment frequency rises if you deploy empty changes, or split one release into ten.
- Change failure rate falls if you stop recording incidents, or redefine "failure".
- Time to restore falls if incidents are closed before the problem is really fixed.
- Lead time falls if people commit late, keeping work hidden on their own machines.
The defences are structural. Look at all four together, because gaming one usually damages another: a push for frequency alone shows up as a rising failure rate. Compare a team with its own past, not with other teams, whose systems, constraints and definitions differ. Let teams own their numbers and choose their improvements. And never attach the metrics to individual performance reviews or bonuses.
Keep them in proportion, too. The four keys measure delivery performance: how well you ship. They say nothing about whether you are building the right thing, whether users are happy, or whether the team is burning out. Pair them with product metrics, with the SLOs from the SRE track, and with regular conversations with the people doing the work.