2026-06-22 · 7 min
DORA Metrics di Tim 3 Engineer SaaS Jakarta
Klien SaaS Jakarta saya operate (~600 paying tenant) punya tim 3 engineer fulltime. Owner minta saya assessment “tim kita produktif tidak?” 6 bulan lalu. Saya implement DORA metrics tracking sederhana. Hasil terukur, dan pattern yang berhasil scale untuk tim kecil tanpa overhead enterprise tooling.
Setup tracking
Tools yang saya pakai:
- GitHub API: source untuk commit, PR, deploy event
- Plausible Analytics: untuk track production deploy via custom event
- Sentry: untuk track incident + alert
- Grafana (self-hosted di Hetzner): visualize semua metric
- Bash + Bun script: nightly cron yang query API, write ke Postgres, push ke Grafana
Total tooling cost: ~$0 (semua existing infrastructure klien).
Implementation effort: 3 hari kerja saya, billed Rp 7,5jt one-time.
4 DORA metrics
1. Deploy Frequency
Frequency tim ship ke production. Pattern:
Cron query GitHub API setiap malam:
const deploys = await octokit.actions.listWorkflowRuns({
owner, repo,
workflow_id: 'deploy-prod.yml',
status: 'success',
created: `>${yesterday}`,
});
Insert ke deploys table dengan timestamp.
Baseline (Januari 2026): ~0,8 deploy/hari (sekitar 4 deploy/minggu).
6 bulan later (Juni 2026): ~3,2 deploy/hari (sekitar 16/minggu).
Improvement 4x. Source:
- Feature flag pattern (deploy backend + UI terpisah, flag-controlled rollout)
- Pipeline build time turun dari 12 menit ke 3,5 menit (parallel job + cache improvement)
- Trunk-based dev: PR small, merge cepat
2. Lead Time for Changes
Time dari first commit ke production deploy.
Saya track via GitHub: ambil first commit di branch, lalu deploy timestamp.
SELECT
pr.merged_at - first_commit.timestamp AS lead_time
FROM pull_requests pr
JOIN commits first_commit ON ...
WHERE pr.merged_at > NOW() - INTERVAL '30 days';
Baseline: median 6,2 hari (P95 14 hari)
Sekarang: median 2,0 hari (P95 4,5 hari)
Improvement 68%. Source:
- Smaller PR (rata-rata dari 480 LOC ke 180 LOC)
- Review SLA explicit (24 jam max, tim disiplin)
- Less time stuck di “waiting for QA” (we shifted left, dev test own work)
3. Change Failure Rate
Percentage of deploys yang cause incident or rollback.
Saya track via convention: PR/commit dengan label hotfix, rollback, atau incident-fix counted as failure-related. Plus Sentry incident yang triggered post-deploy within 4 jam window.
Baseline: 18% (sekitar 1 dari 5,5 deploy ada incident)
Sekarang: 9% (sekitar 1 dari 11 deploy)
Improvement 50%. Source:
- Better test coverage (dari 38% ke 64% di critical path)
- Staging environment dengan production-like data (related: postmortem deploy Jumat sore)
- Pre-deploy smoke check di CI
4. Mean Time to Recovery (MTTR)
Time dari incident detected ke service restored.
Track via Sentry alert timestamp + incident resolution timestamp (manual entry di Linear issue).
Baseline: median 78 menit (P95 4,2 jam)
Sekarang: median 38 menit (P95 1,8 jam)
Improvement 52%. Source:
- Better alerting (Sentry → Telegram dalam < 1 menit dari error spike)
- Runbook ditulis untuk top 5 common incident
- Rollback automation (1-command rollback via GitHub Actions)
Implementation detail tracking
Script bash + Bun nightly:
// scripts/dora-metrics.ts
import { Octokit } from '@octokit/rest';
import { Pool } from 'pg';
const octokit = new Octokit({ auth: process.env.GH_TOKEN });
const db = new Pool({ connectionString: process.env.DATABASE_URL });
async function trackDeploys() {
const since = new Date(Date.now() - 24 * 60 * 60 * 1000);
const { data: runs } = await octokit.actions.listWorkflowRuns({
owner: 'klien-org',
repo: 'app',
workflow_id: 'deploy-prod.yml',
status: 'success',
created: `>${since.toISOString()}`,
});
for (const run of runs.workflow_runs) {
await db.query(`
INSERT INTO dora_deploys (deployed_at, commit_sha, workflow_run_id)
VALUES ($1, $2, $3)
ON CONFLICT (workflow_run_id) DO NOTHING
`, [run.created_at, run.head_sha, run.id]);
}
}
async function trackLeadTime() {
// Query merged PR last 24h, compute lead time per PR
// ...
}
await trackDeploys();
await trackLeadTime();
await trackIncidents();
Cron: 0 1 * * *.
Grafana dashboard: 4 panel (1 per metric), 30-day rolling average + 7-day window comparison.
Yang tim suka
- Transparency: tim bisa lihat sendiri progress. Dorong improvement bottom-up.
- Owner happy: data konkret untuk justify capacity hire atau training budget.
- Onboarding effective: junior dev liat metric, paham target sustainable, bukan rush ship.
Yang bikin tim resist
-
Initial labeling discipline: tim sempat lupa label “rollback” atau “incident-fix”. Stats inaccurate selama 2 minggu pertama. Saya tambah PR template + bot reminder.
-
Metric gaming risk: deploy frequency naik karena tim split PR jadi terlalu kecil. Saya monitor “PR with no functional change” sebagai counter-metric.
-
Lead time skew dari long-lived feature branch: 1 PR yang ditahan 30 hari skew P95. Saya add filter untuk exclude outlier > 14 hari (counted as anomaly).
Cost & ROI
Setup cost (saya): Rp 7,5jt one-time. Maintenance: ~2 jam/bulan (saya audit metric, update script kalau API change).
Saving for klien:
- Less incident (50% reduction × ~Rp 4jt avg incident cost) = ~Rp 2jt/mo
- Faster delivery (lead time -68%) = approx feature velocity gain worth Rp 8-12jt/mo
- Lebih tinggi engineer retention (objective progress visibility = job satisfaction)
Klien very satisfied. Sekarang ini standard practice mereka.
Verdict
DORA metrics worth-it untuk tim engineer SMB 3-10 orang. Bukan untuk solo dev (overhead vs insight gain ratio rendah). Bukan untuk tim 50+ tanpa SRE function (butuh tooling proper, LinearB / Faros AI).
Bukan magic — improvement datang dari practice change (smaller PR, faster review, test coverage), bukan dari metric tracking itu sendiri. Metric expose problem, tim fix-nya.
Pattern simpler dari enterprise tooling, tetap actionable. Saya rekomendasi semua klien SaaS yang punya tim dev > 2 orang untuk implement variant pattern ini.
Ditulis oleh Reza Pradipta