SLO Definition
Define Service Level Objectives that tie technical reliability to user happiness with measurable targets.
Why
An SLO is a number that makes the trade-off between reliability and velocity explicit. Without one, every team optimizes for 100% uptime, which means no risky deploys, no new features, and a slow product — or they deploy recklessly and reliability is a vibe. With an SLO of 99.9% over 28 days, the team gets an error budget of 43 minutes of downtime per month: they can spend it on deploys, feature flags, or experiments, and as long as they're under budget, product velocity is unconstrained. When the budget is burned, deploys freeze until reliability recovers. This converts "should we ship?" from a political argument into an arithmetic check, which is the single biggest contribution SRE makes to an organization.
When
When a service reaches production and has users. Start with one SLO per user-facing service; add more as you mature.
How
1. Identify the user journey and its SLI - SLI = "good events / total events" (e.g., successful checkouts / attempted checkouts) - Pick the journey whose failure = "the service is down" to a user 2. Set the SLO target and window - Target: 99.9% (start here; 99.99% costs ~10x more to achieve) - Window: 28 days (long enough to smooth noise, short enough to act on) - Error budget = (1 - 0.999) × 28 days = 43.2 minutes of allowed downtime 3. Define the SLI measurement - "successful" = HTTP 200 + business success (order actually created, not just 200) - Measure from the user's edge (RUM/synthetic), not the server's internal view 4. Make the budget actionable - Burn rate >2x → freeze risky deploys, focus on reliability - Burn rate <0.5x → deploy freely, you have headroom - Publish the budget to the whole team so it's not a secret 5. Review and adjust quarterly - If you never burn budget → SLO is too loose, tighten it (or ship more) - If you always burn budget → SLO is too tight, loosen it (or invest in reliability)
Example
# SLO: 99.9% of checkout attempts succeed over 28 days
slo:
service: checkout
sli: "successful_checkouts / attempted_checkouts"
target: 0.999
window: 28d
error_budget: 43.2m # (1 - 0.999) * 28d
# SLI measurement (Prometheus):
# successful = rate(http_requests_total{service="checkout",status="200",order_created="true"}[5m])
# total = rate(http_requests_total{service="checkout"}[5m])
# sli = successful / total
# Burn rate alert:
# burn = (1 - sli) / (1 - 0.999)
# burn > 2 for 1h → page (consuming budget 2x fast)
# burn > 1 for 6h → ticket (consuming budget 1x, chronic)
# Policy:
# if burn > 2 → deploy freeze (only fixes, no features) until burn < 1
# if burn < 0.5 → deploy freely (headroom for risky changes)Common Problems
- ⚠Setting SLO to 100% — leaves zero error budget, so every deploy is a reliability risk and velocity drops to zero; 99.9% is the sane starting point.
- ⚠Measuring the SLI from the server's internal view (HTTP 200) instead of the user's edge — a 200 with a broken business outcome (order not created) counts as success.
- ⚠SLO without a budget policy — the number exists but nothing changes when it's burned; the value is in the deploy-freeze policy, not the target.
- ⚠Too many SLOs per service — 5 SLOs means 5 budgets to track and no clear signal; start with one, add only when a second user journey is independently important.
Best Practices
- ✓Start at 99.9% over 28 days — this gives a 43-minute monthly error budget that balances reliability and velocity; tighten only when users demand it.
- ✓Measure the SLI from the user's edge (RUM or synthetic), counting business success not just HTTP 200 — the server's view hides user-visible failures.
- ✓Make the error budget actionable: freeze deploys when burning >2x, allow risky changes when <0.5x — the policy is the value, not the number.
- ✓Review the SLO quarterly: if you never burn budget it's too loose, if you always burn it's too tight — calibrate from real user behavior.