DORA metrics for small teams: the four delivery numbers that matter
Ask a small engineering team how delivery is going and you get adjectives: pretty good, a bit slow, kind of fragile. Ask the same team four specific questions and you get a health record: how often do you deploy, how long from merged to live, what share of deploys cause an incident, and how fast do you undo a bad one? Those are the four DORA metrics — deployment frequency, lead time for changes, change failure rate, and failed-deployment recovery time — and they matter precisely because they fight each other. You cannot max all four by gaming one: shipping constantly raises frequency but wrecks failure rate unless your changes got smaller; hiding failures wrecks recovery time. The tension is the honesty.
This note defines the four in units a five-to-fifteen-person team can actually collect by hand, lists the traps that make each number lie, gives benchmark bands from the DORA research that are worth aiming at (and the smaller band worth starting from), and a one-afternoon instrumentation plan that needs nothing but git and a shared spreadsheet.
1. The four numbers, defined for a small team
- Deployment frequency — how many days per week something ships to production. Count days-with-a-deploy, not deploys-per-day: three deploys before lunch then silence is one day, and that is the honest number. Batch deploys (the Friday 4pm “week's work in one release”) show up as exactly what they are: frequency 1.
- Lead time for changes — hours from merge to production, median. Not from ticket creation — that number is dominated by queue and negotiation, not by your pipeline. If a merged PR waits two days for “the next release window,” lead time is 48 hours, and no re-labeling changes it.
- Change failure rate — the share of production deploys that caused an incident, a rollback, a hotfix, or a customer-visible defect. Count every deploy; mark the failed ones; divide. A rollback is not a separate successful deploy — it is the receipt for a failed one.
- Failed-deployment recovery time — time from customer impact to service restored on a failed change, median. From impact, not from ticket-open: a monitoring gap is part of the cost, and measuring from open flatters the queue instead of the customer.
2. The five traps that make the numbers lie
Counting effort instead of outcomes. Story points, commits, lines of code — none of them survive contact with a customer. If a metric has no deployment date in it, it is a work diary, not a delivery metric.
Vanity micro-deploys. Shipping a typo fix at 9am to start the frequency graph is fine once; a pattern of trivial deploys means frequency stopped measuring flow and started measuring performance theatre. The pair that keeps each other honest is frequency × failure rate — if frequency doubles while failure rate triples, you are shipping risk, not value.
Lead time measured from ticket creation. Then the number includes product debate, backlog time, and the two weeks the ticket sat unassigned — real costs, but the wrong lever. Keep cycle time (ticket-to-merge) and lead time (merge-to-prod) as two separate numbers, or you will “improve” the pipeline by hurrying the backlog.
Recovery from ticket-open, not impact. The customer does not know a ticket exists. If detection relies on a user reporting it, your recovery time includes their wait — which is exactly the number that should hurt.
Quarterly argue-the-data. A team that spends the retro disputing whether a deploy “counts” is spending the effort the metric was meant to save. Decide the counting rules once, in one page, and let imperfect-but-consistent beat precise-but-disputed. (This is the same rule that keeps a post-mortem template short.)
3. Benchmarks: aim at the band, not the elite line
The DORA research (State of DevOps, 2021–2024) publishes four performance bands. For a small team, useful reading:
- Deployment frequency: low is monthly+, medium is weekly-to-monthly, high is at least daily. If you ship weekly you are already ahead of most teams your size; on-demand is a direction, not a requirement.
- Lead time for changes: low is one-to-six months, medium is a week-to-a-month, high is under a week, elite is under a day. The gap from “a month” to “two days” is usually one bottleneck: a release ritual that could be a button.
- Change failure rate: low is 0–15%, high is above 40%. If you are near half, the fix is almost never “test more” in the abstract — it is smaller changes and a rehearsed rollback checklist.
- Recovery time: low is a week-plus, high is under a day, elite is under an hour. Small teams routinely beat elite here on incident response and lose the same points to detection — the fix is a monitoring row, not a war room.
Rule of use: pick one number per quarter to move, and leave the other three as context. Teams that push all four at once improve none, because every lever pulls against another.
4. Instrumentation in one afternoon
- Deploy log (10 min): a one-line append on every production deploy — timestamp, short SHA, service. A shell alias wrapping your deploy command does it; no platform needed.
- Lead time (20 min): the deploy log line plus
git log --mergesgives you merge-to-deploy per release; a spreadsheet column does the arithmetic. Weekly median, not mean. - Failure flag (10 min): add one checkbox to your post-incident template — “caused by deploy #N” — and link the deploy log line. Failure rate is failed/total over the same window.
- Recovery clock (10 min): incident start (impact) and end (restored) already exist in your incident doc; write them in the same row as the deploy number.
- The weekly four-number table (5 min/week): four cells, one trend arrow each, reviewed in the meeting you already run. A number nobody reviews is a number you will stop trusting — the same reason a weekly review checklist keeps the whole ops loop alive.
- One lever per quarter: frequency → shrink the release ritual; lead time → shrink PR size; failure rate → smaller changes plus rollback rehearsal; recovery → detection first (one good saturation/alert row), rollback second. Changing two at once is how teams end up changing zero.
5. Worked example
A six-person B2B scheduling app measures honestly for the first time in March: deploys 1.2 days/week (the Friday batch), lead time 9 days median, change failure rate 30% (the Friday batch has grown to forty-PR releases, so any bad PR ships with nine friends), recovery 6 hours (bad deploys found by customers, rolled back Monday). They pick one lever: release size. PRs capped at one day's work, deploy button pressed whenever the tree is green instead of on Fridays.
Ninety days later: deploys 4.1 days/week, lead time 26 hours, failure rate 12% (small changes fail less and are diagnosed faster), recovery 40 minutes (a failing one-day change has one suspect and a rehearsed rollback). No platform was bought; the total instrumentation is a shell alias and a spreadsheet. The counter-example is the sister team that bought a delivery-analytics platform first, then spent a quarter disputing what a “deploy” was in the tool's config, and ended March with a beautiful dashboard of numbers nobody trusted.
6. Metrics (for the metric itself)
- The four numbers are computed every week, in one table, with counting rules written on one page.
- Exactly one improvement lever per quarter; the other three numbers stay as context, not targets.
- Failure rate and frequency are always read as a pair — neither is ever reported alone.
- Counting-rule disputes get settled in one sentence at the next review, not a tooling migration.
From the HIVE80lab kit
- The First 30 Minutes — free incident quick-start
- Ops Starter Kit — incident response for small teams — $14
- Ops Starter Kit Vol. 2 — advanced incident response & communications — $27
- Ops Mega Bundle — all 5 kits in one download — $49
Related: the deployment rollback checklist is what recovery time is made of, the change-freeze window policy tells you when to stop shipping entirely, and the incident post-mortem template is where the failure flag lives.