Jawaban singkat untuk pertanyaan yang paling sering diajukan pembaca tentang topik ini.
01Apa perbedaan SLI, SLO, dan SLA?
SLI adalah pengukuran kualitas layanan, biasanya rasio event yang baik terhadap event yang valid. SLO adalah target untuk SLI itu dalam satu window, misalnya 99,9% request berhasil selama 30 hari. SLA adalah kontrak yang menempelkan konsekuensi, seperti service credit, jika target meleset.
02Bagaimana cara menghitung error budget?
Kurangi SLO dari 100% lalu kalikan dengan panjang window. Untuk SLO 99,9% selama 30 hari, 0,1% dari 43.200 menit adalah 43,2 menit. Hal yang sama bisa dilakukan dengan request: 0,1% dari 1.000.000 request valid adalah 1.000 kegagalan.
03Mengapa SLO tidak boleh 100%?
Reliability sempurna tidak realistis, dan pengguna tidak bisa membedakannya karena jaringan dan perangkat mereka sendiri lebih sering gagal. Setiap tambahan angka sembilan memotong kegagalan yang diizinkan sepuluh kali lipat dan menaikkan biaya tajam. SLO di bawah 100% menyisakan error budget yang bisa dipakai untuk rilis dan eksperimen.
04Apa yang terjadi jika error budget habis?
Itu ditentukan oleh error budget policy yang ditulis sebelum kejadian. Tindakan umumnya adalah memprioritaskan pekerjaan reliability, membekukan rilis kecuali perbaikan mendesak sampai layanan kembali dalam SLO, dan mengadakan postmortem untuk insiden besar. Tanpa policy, SLO hanyalah laporan.
05Bagaimana mengukur SLI availability di Prometheus?
Bagi rate request gagal dengan rate semua request dari counter http_requests_total, misalnya jumlah rate() respons 5xx dibagi jumlah rate() semua respons. SLI-nya adalah satu dikurangi rasio itu. Rekam per window sebagai recording rule agar burn-rate alert tetap murah.
SLI adalah rasio terukur antara event yang baik dan event yang valid, SLO adalah target untuk rasio itu dalam satu window, dan SLA adalah kontrak dengan konsekuensi jika target meleset. Pasang SLO di bawah 100% dan lebih ketat dari SLA. Selisihnya adalah error budget: 43,2 menit per 30 hari pada 99,9%.
Ketiga singkatan ini sering dipakai bergantian di sprint planning, kontrak vendor, dan status page, dan kebingungannya mahal. Tim menjanjikan 99,99% di kontrak karena angkanya terdengar profesional, lalu sadar bahwa deploy mereka sendiri sudah menghabiskan lebih banyak downtime dari yang diizinkan.
Artikel ini mendefinisikan setiap istilah dengan kalimat dari buku SRE Google, lalu menghitungnya: cara menulis SLI sebagai rasio, cara memilih target, berapa menit kegagalan yang diizinkan tiap target, apa yang dilakukan saat budget habis, cara kerja burn-rate alert, dan PromQL untuk mengukurnya. Output calculator berasal dari run yang saya jalankan untuk artikel ini, dan semua angka lain diturunkan dari rumusnya atau dikutip.
Apa beda SLI, SLO, dan SLA?
Buku SRE mendefinisikan SLI sebagai ukuran kuantitatif yang didefinisikan dengan cermat atas suatu aspek tingkat layanan, SLO sebagai nilai atau rentang nilai target untuk tingkat layanan yang diukur oleh SLI, dan SLA sebagai kontrak eksplisit atau implisit dengan pengguna yang memuat konsekuensi saat SLO terpenuhi atau meleset. Singkatnya: pengukuran, tujuan, janji.
Istilah
Pertanyaan yang dijawab
Contoh
Jika meleset
SLI (indicator)
Bagaimana kondisi layanan sekarang?
Request HTTP yang baik dibagi request HTTP yang valid, diukur dalam 5 menit
Tidak ada. Ini pengukuran, bukan komitmen
SLO (objective)
Tingkat layanan apa yang ingin kita capai?
99,9% request valid berhasil dalam rolling 30 hari
Konsekuensi internal: error budget policy berlaku
SLA (agreement)
Apa yang kita janjikan, dan apa yang kita bayar jika ingkar?
Availability bulanan 99,5%, jika tidak maka service credit (angka ilustrasi)
Kontraktual: credit, refund, atau hak mengakhiri kontrak
Buku SRE memberi uji cepat untuk membedakan SLO dari SLA: tanyakan apa yang terjadi jika target tidak tercapai. Kalau tidak ada konsekuensi yang eksplisit, itu SLO. Kebanyakan produk internal, termasuk backend ERP dan POS yang saya bangun, cukup memakai SLO saja.
Bagaimana menulis SLI yang mencerminkan pengalaman pengguna?
SRE Workbook menyarankan setiap SLI dinyatakan sebagai jumlah event yang baik dibagi jumlah total event yang valid, sehingga nilainya berkisar dari 0% (tidak ada yang jalan) sampai 100% (tidak ada yang rusak). Rasio mudah dijadikan alert, mudah diubah menjadi budget, dan bisa dibandingkan antar layanan. Rasio juga memaksa Anda mendefinisikan dua hal: apa yang dihitung sebagai event, dan apa yang dihitung baik.
Mulailah dari user journey, bukan dari dashboard yang sudah ada. Untuk layar checkout di POS, journey-nya: kasir menekan bayar, transaksi tersimpan, data struk kembali. Workbook mengelompokkan SLI umum menurut jenis sistem, dan empat di antaranya mencakup sebagian besar backend web:
Availability: porsi request valid yang mengembalikan respons non-error. Hitung 5xx sebagai buruk; hitung 4xx sebagai kesalahan pemanggil kecuali bug Anda sendiri yang menyebabkannya.
Latency: porsi request yang lebih cepat dari sebuah threshold, misalnya 300 ms. Nyatakan sebagai percentile atau rasio threshold, karena buku SRE memperingatkan bahwa rata-rata sederhana bisa menyembunyikan tail latency.
Correctness: porsi hasil yang benar. Untuk pipeline atau ledger, ini bisa berarti pemeriksaan rekonsiliasi yang lolos, bukan sekadar request yang mengembalikan 200.
Freshness: porsi data yang lebih baru dari batas tertentu, misalnya stok yang disinkronkan dari cabang dalam 5 menit. Cocok untuk pipeline dan cache, karena jawaban cepat tapi basi tetap sebuah kegagalan.
Workbook menyarankan lima jenis SLI atau kurang yang mencakup fungsi paling kritis. Lebih dari itu, tidak ada yang ingat mana sinyal yang sebenarnya.
Pisahkan spesifikasi SLI dari implementasinya. Spesifikasi adalah hasil yang Anda pedulikan; implementasi adalah cara mengukurnya. Log load balancer, metric server, dan synthetic probe adalah tiga implementasi dari SLI availability yang sama, masing-masing dengan cakupan dan biaya berbeda.
Mengapa SLO harus di bawah 100%?
Karena 100% tidak mungkin dicapai dan mengejarnya mahal. Buku SRE menyebut tidak realistis dan tidak diinginkan untuk memaksa SLO terpenuhi 100% waktu: pengguna berada di balik jaringan, ponsel, dan ISP yang kurang andal dibanding layanan Anda, sehingga mereka tidak bisa membedakannya, dan usaha ekstra memperlambat setiap rilis.
Setiap tambahan satu angka sembilan memotong kegagalan yang diizinkan sepuluh kali lipat. Dari 99,9% ke 99,99%, budget 30 hari menyusut dari 43,2 menit menjadi 4,32 menit, sehingga satu deploy buruk selama 5 menit saja sudah melanggar target. Biayanya adalah redundancy sungguhan, mesin rollout, dan rotasi on-call. Artikel saya tentang high availability, redundancy, dan failover design membahas biaya infrastruktur dari angka sembilan itu; di sini intinya hanya bahwa target harus yang sanggup Anda tanggung.
Jangan juga menyalin target dari performa hari ini. Buku SRE menyarankan untuk tidak memilih target berdasarkan performa saat ini, karena itu mengunci kebetulan apa pun yang kebetulan Anda ukur. Pilih dari kebutuhan pengguna, lalu cek apakah bisa dipenuhi. Untuk API POS di satu VPS, saya akan mulai di 99,5% lalu naik bertahap, bukan mengumumkan empat sembilan lalu berharap.
Bagaimana hubungan SLA dengan SLO?
SLA adalah konsekuensi kontraktual dari sebuah SLO, dan SLO di belakangnya sebaiknya lebih ketat dari yang dijanjikan di kontrak. Buku SRE merekomendasikan SLO internal yang lebih ketat dari yang diiklankan ke pengguna, sehingga ada ruang untuk memperbaiki masalah kronis sebelum pelanggan sadar dan untuk menukar performa dengan biaya.
Memakai angka ilustrasi dari tabel: SLA 99,5% mengizinkan 216 menit kegagalan per 30 hari (0,005 kali 43.200 menit), sedangkan SLO internal 99,9% hanya mengizinkan 43,2. Alarm internal berbunyi jauh sebelum credit terutang. Kalau SLO dan SLA angkanya sama, peringatan pertama Anda adalah invoice.
Bagaimana cara menghitung error budget?
Error budget adalah 100% dikurangi SLO. Kalikan dengan panjang window untuk mendapat waktu, atau dengan jumlah request valid untuk mendapat jumlah kegagalan yang boleh terjadi. Window 30 hari berisi 30 kali 24 kali 60 = 43.200 menit, jadi setiap SLO langsung bisa dikonversi.
SLO
Budget per 30 hari
Budget dalam detik
Request gagal per 1 juta
99%
432 menit (7,2 jam)
25.920
10.000
99,9%
43,2 menit
2.592
1.000
99,95%
21,6 menit
1.296
500
99,99%
4,32 menit
259,2
100
Daripada percaya hitungan di kepala, saya menulis calculator dalam TypeScript lalu menjalankannya. Outputnya menampilkan budget tiap SLO dan, untuk bagian burn rate di bawah, seberapa cepat suatu burn rate menghabiskan budget 99,9%.
const WINDOW_DAYS = 30;
const WINDOW_MINUTES = WINDOW_DAYS * 24 * 60; // 43200
const WINDOW_HOURS = WINDOW_DAYS * 24; // 720
// The budget is whatever the SLO leaves over: 100% minus the target.
const budgetFraction = (slo: number): number => 1 - slo;
const budgetMinutes = (slo: number): number =>
budgetFraction(slo) * WINDOW_MINUTES;
// With 1,000,000 valid requests in the window, how many may fail?
const budgetRequests = (slo: number, validRequests: number): number =>
budgetFraction(slo) * validRequests;
// Burn rate 1 spends the budget in exactly the window. Burn rate B spends it in window / B.
const hoursToExhaust = (burnRate: number): number => WINDOW_HOURS / burnRate;
// Share of the whole window's budget consumed by one alert window at a given burn rate.
const budgetConsumed = (burnRate: number, alertWindowHours: number): number =>
(burnRate * alertWindowHours) / WINDOW_HOURS;
for (const slo of [0.99, 0.999, 0.9995, 0.9999]) {
const mins = budgetMinutes(slo);
console.log(
(slo * 100).toFixed(2).padStart(6) + "% " +
mins.toFixed(2).padStart(7) + " min " +
(mins * 60).toFixed(1).padStart(8) + " s " +
budgetRequests(slo, 1_000_000).toFixed(0).padStart(6) + " failed of 1M requests",
);
}
// [burn rate, long window in hours, short window in minutes]
const rules: Array<[number, number, number]> = [
[14.4, 1, 5],
[6, 6, 30],
[1, 72, 360],
];
for (const [burn, longHours, shortMinutes] of rules) {
console.log(
"burn " + String(burn).padEnd(4) +
" long " + String(longHours).padStart(2) + " h, short " + String(shortMinutes).padStart(3) + " min" +
" error ratio above " + (burn * budgetFraction(0.999)).toFixed(4) +
" consumes " + (budgetConsumed(burn, longHours) * 100).toFixed(1) + "%" +
" budget gone in " + hoursToExhaust(burn).toFixed(1) + " h",
);
}
Ini output asli dari menjalankannya dengan type stripping bawaan Node.js:
$ node budget-calc.ts
99.00% 432.00 min 25920.0 s 10000 failed of 1M requests
99.90% 43.20 min 2592.0 s 1000 failed of 1M requests
99.95% 21.60 min 1296.0 s 500 failed of 1M requests
99.99% 4.32 min 259.2 s 100 failed of 1M requests
burn 14.4 long 1 h, short 5 min error ratio above 0.0144 consumes 2.0% budget gone in 50.0 h
burn 6 long 6 h, short 30 min error ratio above 0.0060 consumes 5.0% budget gone in 120.0 h
burn 1 long 72 h, short 360 min error ratio above 0.0010 consumes 10.0% budget gone in 720.0 h
Angkanya cocok dengan tabel, dan cocok dengan 43,2 menit untuk 99,9% selama 30 hari. Budget berbasis waktu mengasumsikan traffic stabil; budget berbasis request (kolom terakhir) lebih adil, karena outage sepuluh menit jam 3 pagi menghabiskan lebih sedikit request gagal dibanding outage yang sama saat jam makan siang.
Window adalah bagian dari SLO. 99,9% per hari mengizinkan 86,4 detik, 99,9% per kuartal mengizinkan 129,6 menit (0,001 kali 129.600). Sebutkan window yang dimaksud, dan pilih rolling window dibanding bulan kalender agar budget tidak reset setiap tanggal 1.
Apa yang terjadi saat error budget habis?
Error budget policy menentukan sejak awal apa yang dilakukan tim saat budget habis. Workbook tegas bahwa tanpa policy, kepatuhan SLO hanyalah satu metric laporan lagi. Tulis, tunjuk owner dan jalur eskalasi, dan sertakan tindakan seperti berikut:
Utamakan bug reliability dan action item postmortem di atas fitur baru.
Bekukan rilis sampai layanan kembali dalam SLO. Contoh di Workbook menghentikan semua perubahan kecuali isu P0 dan perbaikan keamanan.
Wajibkan postmortem saat satu insiden menghabiskan porsi besar budget. Contohnya lebih dari 20% budget dalam empat minggu.
Putuskan bagaimana outage akibat dependency dihitung. Workbook condong ke freeze apa pun penyebabnya, tetapi menyebut pilihan yang tepat bergantung pada layanan dan harus ditulis di policy.
Kebalikannya juga penting. Budget yang nyaris tidak tersentuh adalah sinyal untuk rilis lebih cepat atau mengambil risiko lebih besar, karena reliability yang tidak Anda butuhkan adalah velocity yang Anda buang.
Bagaimana cara kerja burn-rate alert?
Alert untuk setiap lonjakan error hanyalah noise, dan alert berbasis threshold mentah mengabaikan budget. Workbook mendefinisikan burn rate sebagai seberapa cepat, relatif terhadap SLO, layanan menghabiskan error budget. Burn rate 1 menghabiskan budget tepat dalam window SLO; burn rate 14,4 menghabiskannya 14,4 kali lebih cepat.
Setup multi-window, multi-burn-rate yang direkomendasikan untuk SLO 99,9% memanggil on-call pada burn cepat dan membuat tiket pada burn lambat. Setiap alert butuh dua window yang benar bersamaan: window panjang untuk membuktikan burn itu signifikan, dan window pendek, sekitar seperdua belas dari yang panjang, untuk membuktikan burn masih berlangsung. Kolom terakhir diturunkan dari burn rate dan window 720 jam.
Severity dan burn rate
Window panjang dan pendek
Budget terpakai
Budget habis dalam
Page di 14,4
1 jam dan 5 menit
2%
50 jam
Page di 6
6 jam dan 30 menit
5%
120 jam
Ticket di 1
3 hari dan 6 jam
10%
720 jam
Hitungannya singkat: 14,4 kali 1 jam dibagi 720 jam sama dengan 2%, itulah sebabnya burn selama satu jam pada laju itu layak membangunkan seseorang. Window pendek juga mencegah alert tetap merah satu jam setelah masalahnya Anda perbaiki.
Bagaimana mengukur SLI availability di Prometheus?
Jika layanan Anda mengekspos counter http_requests_total, SLI-nya adalah rasio dari rate. Dokumentasi Prometheus menyebut rate() menerima range vector, hanya boleh dipakai pada counter, dan menyesuaikan counter reset setelah restart. Rekam rasio error per window agar alert tetap murah. Label untuk status code bergantung pada client library; di sini saya memakai code, dan banyak setup NestJS menamainya status_code.
groups:
- name: api-slo
rules:
# Bad events / valid events over 5 minutes. 4xx is the caller's mistake, so it
# stays in the denominator but never in the numerator.
- record: job:slo_errors_per_request:ratio_rate5m
expr: |
sum by (job) (rate(http_requests_total{job="api", code=~"5.."}[5m]))
/
sum by (job) (rate(http_requests_total{job="api"}[5m]))
# Same expression, longer range. Repeat for 30m, 6h and 3d.
- record: job:slo_errors_per_request:ratio_rate1h
expr: |
sum by (job) (rate(http_requests_total{job="api", code=~"5.."}[1h]))
/
sum by (job) (rate(http_requests_total{job="api"}[1h]))
Counter yang sama memberi SLI untuk seluruh window SLO. Untuk latency, histogram memungkinkan Anda membagi request di bawah threshold dengan semua request, yang hasilnya eksak, tidak seperti percentile hasil interpolasi:
# Availability SLI over the SLO window: good / valid. Run it as a recording rule in
# production, because a 30d range query over raw counters is slow.
1 - (
sum(increase(http_requests_total{job="api", code=~"5.."}[30d]))
/
sum(increase(http_requests_total{job="api"}[30d]))
)
# Latency SLI: share of requests faster than 300 ms. The le="0.3" bucket must exist
# in your histogram, so pick the threshold from your bucket boundaries, not the reverse.
sum(rate(http_request_duration_seconds_bucket{job="api", le="0.3"}[5m]))
/
sum(rate(http_request_duration_seconds_count{job="api"}[5m]))
# p99 for dashboards (keep le in the aggregation). Do not alert on this one.
histogram_quantile(0.99,
sum by (le) (rate(http_request_duration_seconds_bucket{job="api"}[5m])))
Lalu pasang alert dari tabel. Expression ini mengikuti contoh Workbook untuk SLO 99,9%, sehingga fraksi budget-nya 0,001:
groups:
- name: api-slo-alerts
rules:
# SLO 99.9%, so the budget fraction is 0.001. Both windows must exceed the
# threshold: the long one proves it is significant, the short one proves it is
# still happening.
- alert: ApiErrorBudgetFastBurn
expr: |
(
job:slo_errors_per_request:ratio_rate1h{job="api"} > (14.4 * 0.001)
and
job:slo_errors_per_request:ratio_rate5m{job="api"} > (14.4 * 0.001)
)
or
(
job:slo_errors_per_request:ratio_rate6h{job="api"} > (6 * 0.001)
and
job:slo_errors_per_request:ratio_rate30m{job="api"} > (6 * 0.001)
)
labels:
severity: page
- alert: ApiErrorBudgetSlowBurn
expr: |
job:slo_errors_per_request:ratio_rate3d{job="api"} > 0.001
and
job:slo_errors_per_request:ratio_rate6h{job="api"} > 0.001
labels:
severity: ticket
Layanan tanpa traffic menghasilkan 0 dibagi 0, yang dikembalikan Prometheus sebagai NaN, sehingga alert diam-diam tidak pernah menyala. Tambahkan synthetic probe atau alert absent() agar keheningan pada sebuah counter ikut terdeteksi.
Aturan yang saya bawa pulang: SLI adalah rasio yang bisa dihitung, SLO adalah angka di bawah 100% yang sanggup ditanggung, dan SLA hanyalah apa yang bersedia Anda bayar jika meleset, dipasang lebih longgar dari SLO. Mulai dengan satu SLI availability dan satu SLI latency, ubah target menjadi menit, tulis policy sebelum outage pertama, dan beri alert berdasarkan burn rate, bukan error mentah.