DORA metrics

Embed
Preview of the card
<a href="https://watchtowerops.net/docs/dora"><img src="https://watchtowerops.net/docs/_api/public/orgs/aa5959cb-1a0b-4a9a-bc9a-913e7ac31cd9/spaces/b7aac181-9916-4805-b253-becc5fd2ca62/pages/68bc7699-3374-48c5-8cf1-2c1efbf0107a/social-card.svg?v=3e7ae33eec8b" alt="DORA metrics" width="600" height="315"></a>

GET /v1/projects/{p}/dora?from&to&service&team&env returns the four DORA metrics and a band for each.

Metric

Source

Elite

High

Medium

Low

Deployment frequency

finished deployments / days in range

>= 1 per day

>= 1 per week

>= 1 per month

less

Lead time for changes

median of deployment time minus the oldest commit time of the release

< 1 day

< 1 week

< 30 days

more

Change failure rate

deployments that ended failed (a rollback marks the replaced one failed), or were followed within 24 h by an incident or an issue regression, over all deployments

<= 5%

<= 10%

<= 15%

more

Time to restore

median of incident resolved minus declared

< 1 hour

< 1 day

< 1 week

more

The overall band is the lowest band among the metrics that have data. These are our reading of the published DORA bands.

Incidents are the project's own incidents plus incidents imported from the SCM (below). An issue regression counts against a deployment of the same service (or any service, for a project-wide deployment).

History import and sync (backfill)

Settings live on the CI page, DORA tab, "History import". GET /v1/projects/{p}/dora/backfills lists the jobs and the connected installations and repositories they can use; POST with {installation_id, repo, since_days (1-730, default 90), incident_label (default "incident")} queues one (posting the same repository again restarts it); DELETE .../dora/backfills/{id} stops it. Reads need read_telemetry, changes manage_project.

The notifier runs each job as the installing user, through the same internal actions as the webhooks:

  1. Deployments. GitHub deployments with their final status (success/inactive succeeded, failure/error failed), GitLab deployments (success, failed), Bitbucket Pipelines deployments (SUCCESSFUL, FAILED). A deployment to an environment the project does not have is counted as skipped. When exactly one service's repository link (or catalog repo_url) names the repository, the deployment is that service's.

  2. Commits. For each release, the commits since the previous deployment to the same environment (the deployed commit alone for the first one), with commit times, authors and files. Release commits that arrived without committed_at (a deploy script that sends only the sha) get it from the provider, so lead time has data.

  3. Incidents. GitHub issues labelled incident_label; GitLab issues of type incident or with that label. Bitbucket has none. A closed issue is a resolved incident.

A finished job syncs again every 6 hours from where it stopped (with one hour of overlap). A failed one retries with backoff, or when the provider's rate limit resets. Everything is idempotent: deployments carry the provider's id (external_id, also set by the GitHub and GitLab deployment webhooks, so a webhook and a backfill never record one deployment twice), commits and incidents are upserts. Azure Repos has no deployment API of its own (deployments live in Azure Pipelines), so it is not a backfill source; use the CI webhook or wtctl release create --deploy.

Limits: one run imports at most 2000 deployments and 1000 incident issues; the next sync continues. Lead time is per release commit, not per pull request.

Updated