Most teams that adopt SLOs start by picking a round number — "99.9% uptime" — and stop there. That number is worthless without an SLI that measures something a user actually feels, and it is dangerous without an error budget policy that tells you what to do when you're burning through it. This is the version of SLOs I actually use: how to pick SLIs, how to set an SLO you can defend in a postmortem, and how burn-rate alerting turns an error budget from a spreadsheet metric into something that pages a human at the right time.
Choosing SLIs that reflect user pain
An SLI (service level indicator) is a single measurement of behaviour, expressed as a ratio of good events to valid events over a window — for example, the proportion of HTTP requests that complete in under 300ms with a non-5xx status. The trap is measuring what's easy to measure (CPU, memory, uptime pings) instead of what the user experiences. A service can have 100% uptime by that definition and still be unusable if every request takes 8 seconds. Start from the user journey: checkout completing, a search returning results, a webhook being delivered within its retry window. Each of those maps to one or two SLIs — usually a request-based availability SLI (fraction of requests that succeed) and a latency SLI (fraction of requests under a threshold).
Setting an SLO you can defend
The SLO (service level objective) is the target you set on top of the SLI — say, "99.5% of checkout requests succeed in under 500ms, measured over a rolling 28 days." Do not copy a competitor's number or pick 99.99% because it sounds impressive. Look at your last two or three months of actual SLI data first; if you've been running at 99.7% without anyone noticing, setting the SLO at 99.5% gives you real room to ship risky changes, while setting it at 99.95% locks you into a reliability posture you haven't proven you can sustain. The SLO should be slightly looser than your historical performance, not aspirational.
A single backend service might support five different SLOs if it serves five different user-facing flows with different pain tolerances (a background sync job can tolerate more latency than a login flow). Resist the urge to define one blanket SLO per microservice — it hides the failure modes users actually notice.
Error budgets turn SLOs into decisions
The error budget is just 100% minus your SLO, expressed as an allowance: at 99.5% over 28 days, you have a 0.5% budget, which is about 3.6 hours of full downtime equivalent (or a proportionally larger amount of partial degradation). The budget's value isn't the number itself — it's the policy attached to it. A basic error budget policy says: while budget remains, ship features and take normal risk; once the budget is exhausted, freeze feature releases and put the team on reliability work until the budget recovers. Without that policy, an SLO is just a dashboard nobody acts on.
groups:
- name: slo-burn-rate
rules:
- alert: CheckoutErrorBudgetFastBurn
expr: |
(
sum(rate(http_requests_total{job="checkout",status=~"5.."}[1h]))
/
sum(rate(http_requests_total{job="checkout"}[1h]))
) > (14.4 * 0.005)
for: 2m
labels:
severity: page
annotations:
summary: "Checkout burning error budget 14.4x faster than sustainable"
description: >
At this burn rate the 28-day error budget is exhausted in ~2 days.
Page immediately; this is a fast-burn incident, not a trend to watch.
- alert: CheckoutErrorBudgetSlowBurn
expr: |
(
sum(rate(http_requests_total{job="checkout",status=~"5.."}[6h]))
/
sum(rate(http_requests_total{job="checkout"}[6h]))
) > (6 * 0.005)
for: 15m
labels:
severity: ticket
annotations:
summary: "Checkout burning error budget 6x faster than sustainable"
description: "Slow burn — file a ticket, review during business hours."
Burn-rate alerting: why multiple windows matter
A naive alert that fires whenever the SLI dips below the SLO threshold either triggers constantly on noise or misses real incidents entirely, depending on the window size. Burn-rate alerting fixes this by asking a different question: "at the current error rate, how fast am I consuming the error budget relative to a sustainable pace?" A burn rate of 1 means you're on track to exhaust the budget exactly at the end of the SLO window (a sustainable pace). A burn rate of 14.4 over a 1-hour window means you'd exhaust a 28-day budget in about 2 days — that's a page-now situation. Google's SRE workbook popularized the two-window approach shown above: a short, high-threshold window for fast burns that need immediate paging, and a longer, lower-threshold window for slow burns that just need a ticket. Using a single flat threshold on one window is the most common mistake teams make when they first wire up burn-rate alerts.
If your SLO is 99.5% and you alert whenever the rolling SLI drops below 99.5%, you'll get paged for blips that recover on their own and you'll miss slow leaks that never dip below the line in any single short window. Burn rate, not raw SLI value, is the thing to alert on.
Wrapping up
SLOs, SLIs, and error budgets are three different tools solving three different problems: the SLI tells you what to measure, the SLO tells you what target matters, and the error budget policy tells you what to do about it. Skip any one of the three and you end up with a metric nobody trusts, a target nobody defends, or an alert nobody acts on. Get all three right and error budgets stop being a report you generate for a quarterly review and start being the thing that decides, on a Tuesday afternoon, whether the team ships the next feature or fixes the thing that's actually breaking.
Independent software engineer in Nairobi specialising in Acumatica customisations, Laravel backends, and tax fiscalisation integrations across East and Southern Africa.