SRE Guide: SLI, SLO, SLA & Multi-Window Burn Rate Alerting¶
Skill metadata
Name sli-slo-error-budget-design · Level senior · Tags sre slo sli sla error-budget observability prometheus
"SLI, SLO and SLA design: indicator selection with explicit good-events and valid-events definitions, availability and latency target setting, error-budget accounting and freeze policy, and multi-window multi-burn-rate alerting. Use when defining reliability targets or an SLO target for a user-facing API or service, replacing noisy threshold alerts with burn-rate alerts, or governing releases against a spent budget."
Source: skills/sre-slo-sla-observability/sli-slo-error-budget-design/SKILL.md
When to Use This Skill¶
Triggers — load this skill when:
- A service needs SLIs and SLOs defined from real user journeys
- Noisy threshold alerts should become multi-window burn-rate alerts
- An error-budget policy must govern release or freeze decisions
Route elsewhere when:
- Collector, dashboard, and tracing plumbing ->
prometheus-grafana-otel-tracing - Host-level saturation alerting ->
infrastructure-host-monitoring - Delivery throughput metrics ->
devops-metrics-dora-kpis
1. Core Terminology & Formula Matrix¶
For a 99.9% SLO over a 30-day rolling window:
- Total Allowable Downtime / Bad Requests = \(0.1\%\) (\(43.2\) minutes over \(30\) days).
2. Multi-Window Multi-Burn-Rate Alerting Architecture¶
Google SRE recommends alerting on multiple burn rates to balance alert precision and recall:
| Alert Severity | Burn Rate | % Budget Consumed | Short Window | Long Window | Notification Target |
|---|---|---|---|---|---|
| Page (P1) | \(14.4\times\) | \(2\%\) in 1h (100% in 2 days) | 5 mins | 1 hour | PagerDuty / On-call |
| Page (P2) | \(6\times\) | \(5\%\) in 6h (100% in 5 days) | 30 mins | 6 hours | PagerDuty / On-call |
| Ticket (P3) | \(1\times\) | \(10\%\) in 3 days (100% in 30d) | 6 hours | 3 days | Jira / Slack Channel |
3. Prometheus / PromQL Production Multi-Window Alert¶
groups:
- name: slo_checkout_latency
rules:
- alert: CheckoutLatencySLOBurnRateHigh
expr: |
(
sum(rate(http_request_duration_seconds_count{service="checkout",le="0.5",status="200"}[5m]))
/
sum(rate(http_request_duration_seconds_count{service="checkout"}[5m])) < 0.9856
)
and
(
sum(rate(http_request_duration_seconds_count{service="checkout",le="0.5",status="200"}[1h]))
/
sum(rate(http_request_duration_seconds_count{service="checkout"}[1h])) < 0.9856
)
for: 2m
labels:
severity: page
tier: p1
annotations:
summary: "High 1h SLO burn rate (14.4x) on Checkout service"
description: "Over 2% of 30-day error budget consumed within the last hour."
runbook_url: "https://wiki.corp/runbooks/checkout-slo"
4. Good Events, Valid Events & the Budget Policy¶
An SLI is only unambiguous when written as a ratio of explicitly defined event sets:
- valid events: requests the service is accountable for — excludes health checks, excludes load-test traffic, includes every real user request that reached the edge.
- good events: valid events that met the quality bar — e.g. HTTP status not in 5xx and served in under 300 ms. State the latency bound inside the definition; "availability" without a latency clause silently passes requests that took 40 seconds.
# Availability SLI, 28-day rolling, explicit good/valid sets
sum(rate(http_requests_total{job="checkout",code!~"5..",path!="/healthz"}[28d]))
/
sum(rate(http_requests_total{job="checkout",path!="/healthz"}[28d]))
The error budget policy is the part with teeth. Agree it with the business before the budget is spent, and write down what changes automatically:
| Budget consumed | Consequence (pre-agreed, automatic) |
|---|---|
| < 50% | Normal delivery; ship freely |
| 50–90% | Reliability work is prioritised into the next sprint; risky migrations deferred |
| > 100% (exhausted) | Feature freeze: only reliability fixes and security patches ship until the trailing window recovers |
| Exhausted twice in a quarter | SLO or architecture is wrong — re-derive the objective with the product owner |
An SLO with no freeze condition is a dashboard, not an objective.
5. Anti-Patterns¶
| Anti-pattern | Why it fails in production |
|---|---|
| Setting the SLO at 99.99% because it sounds serious | An unreachable target is missed permanently, the error budget is always exhausted, and the freeze policy becomes something everyone ignores. Derive the target from measured performance and what users actually need. |
| Availability defined without a latency clause | A request served in 40 seconds counts as "good", so the SLO stays green through an outage users can plainly feel. Put the latency bound inside the good-events definition. |
| Measuring at the server, not the user's edge | Server-side metrics miss DNS, TLS, CDN and the failures that never reached your process — exactly the ones users report. Measure as close to the client as the architecture allows. |
| Health-check and synthetic traffic counted as valid events | Constant successful probes inflate the ratio and mask real user failures. Exclude probes explicitly from the valid-events set. |
| Alerting on the SLO threshold rather than burn rate | A threshold alert fires on every one-minute blip and stays silent through a slow burn that consumes the quarter's budget. Multi-window multi-burn-rate is the fix. |
| An error-budget policy with no pre-agreed consequence | If nothing changes when the budget is exhausted, the SLO is a dashboard. Agree the freeze condition with the business before it is needed, when it is still an abstract discussion. |
| One SLO for a service with many journeys | Checkout and marketing pages average into a number that describes neither. Set SLOs per critical user journey. |