system-design

SLIs, SLOs, SLAs, and Error Budgets

Three acronyms that turn “the system should be reliable” from a wish into a number you can engineer toward — and one idea (error budgets) that reframes the whole velocity-vs-stability argument.

Prerequisites: Availability, Monitoring & Alerting Time to read: ~18 minutes


The problem

“The system should be highly available.” Everyone agrees, and it means nothing. How available? Who decides? What happens when we miss it? Is 99.9% enough, or do we need 99.99% (which costs 10× more)?

🚨 Without a number, reliability arguments are just opinions, and every decision — ship faster or be more careful? — becomes a fight between the product team (wants velocity) and the ops team (wants stability), with no shared framework to resolve it.

SLIs, SLOs, and SLAs give you the number. Error budgets give you the framework to make decisions with it.


The three, precisely

🚨 These are constantly confused. Get them straight:

Term Is Example
SLI (Indicator) The measurement — what you actually observe “99.95% of requests returned 2xx in under 300ms last month”
SLO (Objective) Your internal target — what you engineer toward “99.9% of requests under 300ms”
SLA (Agreement) The contractual promise with penalties “99.5% uptime or you get a refund”

The relationship, and the key insight:

SLI (what happened)  →  measured against  →  SLO (your target)
                                                 ↓  (looser)
                                             SLA (customer promise, with penalties)

🚨 The SLA is always looser than the SLO, deliberately. If you promise customers 99.5% (SLA) but target 99.9% internally (SLO), you have a buffer — you can miss your internal target and still not breach the contract or owe refunds. Setting your SLA equal to your SLO means every internal miss is a financial and legal event. The gap is your margin of safety.

🎙️ “The SLI is what we measure, the SLO is what we engineer toward, and the SLA is what we promise customers — and I’d keep the SLA looser than the SLO so an internal miss doesn’t automatically become a refund. The SLA is the least interesting number; the SLO is what actually drives engineering.”


Choosing good SLIs

An SLI should measure what users actually experience, not internal conditions.

🚨 Good SLIs are symptom-based (same principle as alerting):

Good SLI (user-facing) Bad SLI (internal)
% of requests served successfully CPU utilization
% of requests under 300ms Number of servers
% of data durable Disk space
Freshness of data (for a pipeline) Queue depth

Common SLI types:

🚨 Measure at the point the user experiences it — ideally at the load balancer or client, not deep inside a service. A service can report 100% success while the load balancer returns errors the service never saw.


Setting the SLO: don’t reflexively pick more nines

🚨 A common mistake: aiming for 99.99% by default. Each nine costs roughly 10× more (the nines), and past a point users can’t even tell the difference.

Set the SLO from what users actually need:

🎙️ “I wouldn’t reflexively target four nines — each nine is roughly 10× the cost, and if our users are on mobile connections that are themselves 99% reliable, extra backend nines are invisible to them. I’d set the SLO where reliability stops mattering to users and spend the difference on features.”

This “don’t over-target reliability” point is a strong, counter-intuitive interview signal.


Error budgets: the reframe

🚨 The most important idea here, and the thing that resolves the velocity-vs-stability fight.

If your SLO is 99.9%, you’re allowed to be unavailable 0.1% of the time — about 43 minutes a month. That 0.1% isn’t failure; it’s a budget.

SLO: 99.9%  →  Error budget: 0.1%  →  ~43 minutes/month of allowed unavailability

Why this changes everything:

🎙️ “Error budgets are what make this useful. 99.9% means we’re allowed 43 minutes of downtime a month — that’s not failure, it’s budget. If we have budget left, we ship aggressively; if we’ve blown it, we freeze features and fix reliability. It turns a political fight into a data-driven decision.”

This is Google SRE’s central operational innovation, and articulating it well is a genuine senior signal.


Error budgets and alerting

The two connect directly: you alert on error-budget burn rate, not static thresholds.

This ties your alerting to the SLO, so alerts fire in proportion to actual user impact. → Monitoring & Alerting


Practical pitfalls

🚨 The “100% SLO” trap. Never target 100% — it’s impossible (dependencies fail, deploys happen), infinitely expensive to approach, and leaves zero error budget, meaning you can never take any risk, ship anything, or do maintenance. A 100% SLO is a sign someone doesn’t understand the framework. The gap between 100% and your SLO is the room you have to operate.

Measure over a meaningful window — usually 28–30 days (a rolling month). Too short and single blips dominate; too long and you can’t react.

Multiple SLOs for one service — availability and latency, since a service can be “up” but too slow to be usable.

Dependencies constrain your SLO. 🚨 You can’t offer 99.99% if a critical dependency offers 99.9% — your SLO is bounded by your dependencies (availability multiplies). Know your dependency SLOs before promising yours.

Not everything needs an SLO. Focus on the critical user journeys (checkout, login, core reads), not every endpoint. An SLO on an admin endpoint nobody depends on is noise.


⚖️ Trade-offs

Choice Gain Cost
Higher SLO (more nines) More reliable ~10× cost per nine; diminishing user benefit
SLA looser than SLO Buffer before penalties “We could promise more” pressure
Error budgets Data-driven velocity/stability decisions Requires org buy-in and discipline to enforce
Symptom-based SLIs Reflect real user experience Must measure at the right point
Fewer, focused SLOs Meaningful, actionable Some services uncovered

In the real world


🚨 Interview traps


🎙️ Soundbites


🛠️ Try it

1. Define SLIs, SLOs, and an SLA for a service. Pick a real service. Write: two SLIs (availability and latency, symptom-based), an SLO for each, and an SLA looser than the SLOs. Getting the three levels distinct and correctly ordered is the exercise — most people conflate them on the first try.

2. Compute an error budget and spend it. For a 99.9% SLO, calculate the monthly error budget (~43 min). Then simulate: a bad deploy burns 20 minutes; a dependency outage burns 30. You’ve now blown the budget — what does that mean for the next deploy? Feel the framework drive the decision.

3. Implement burn-rate calculation. From your error rate, compute how fast you’re consuming the error budget. Distinguish a fast burn (page) from a slow burn (ticket). This connects SLOs to alerting.

4. Justify an SLO to a skeptic. Argue why you’d target 99.9% not 99.99% for a given service. Compute the cost difference and the user-visible difference. If the users are on flaky mobile, the argument writes itself — and that’s the counter-intuitive insight worth internalizing.


Check yourself

1. What's the difference between an SLI, an SLO, and an SLA? An **SLI** (Service Level Indicator) is the *measurement* — the actual observed value of a reliability metric, like "99.95% of requests returned successfully in under 300ms last month." An **SLO** (Service Level Objective) is your *internal target* for that indicator — "99.9% of requests under 300ms" — the number you engineer toward and alert on. An **SLA** (Service Level Agreement) is a *contractual promise* to customers, with financial or legal penalties for breach — "99.5% uptime or you get a refund." The chain: you measure the SLI, compare it against your SLO, and the SLA (deliberately looser than the SLO) is what you guarantee externally. The SLA should always be looser than the SLO so that missing your internal target still leaves margin before you breach a contract.
2. Why should the SLA be looser than the SLO? To create a buffer between "we missed our internal target" and "we breached a contract and owe penalties." If your SLA promises customers 99.5% but you target 99.9% internally, then a bad month that drops you to 99.7% misses your SLO (triggering internal reliability focus) but is still well above the 99.5% you promised — no refunds, no contract breach. If instead the SLA equals the SLO (both 99.9%), then *every* internal miss is simultaneously a financial and legal event, leaving no room to have an off month, do risky maintenance, or absorb a dependency's failure. The gap between the SLA and the SLO is your margin of safety — it lets you manage reliability internally without every fluctuation becoming a customer-facing penalty.
3. What is an error budget and how does it change decision-making? An error budget is the amount of unreliability you're *allowed* by your SLO: a 99.9% SLO permits 0.1% failure, about 43 minutes of downtime per month. Reframing that 0.1% as a budget rather than a failure transforms the velocity-vs-stability argument from opinion into arithmetic. "Never go down" is impossible and leads to never shipping (every change is a risk); "stay within 43 minutes a month" is a concrete resource you spend deliberately. The decision rule becomes data-driven: if budget remains, you can ship aggressively, take risks, and deploy freely; if the budget is exhausted, you freeze features and focus on reliability until it recovers. This aligns product and engineering on a shared number instead of a political fight — the budget, not who argues hardest, decides whether the next priority is a feature or reliability work.
4. Why is targeting a 100% SLO a mistake? Several reasons. It's impossible — dependencies fail, networks partition, deploys occasionally break things, and physical infrastructure has non-zero failure rates, so no real system achieves 100% over any meaningful period. It's infinitely expensive to even approach — each additional nine costs roughly 10× more, and 100% is the asymptote you can never reach. And critically, it leaves *zero error budget*: with a 100% target, any downtime at all is a violation, which means you can never take a risk, ship a change, or perform maintenance without "failing" your SLO — paralyzing the team. The whole error-budget framework depends on the gap between 100% and your SLO being the room you have to operate. A 100% SLO signals that someone doesn't understand the framework; the right target is the point where more reliability stops mattering to users.
5. Why shouldn't you reflexively target more nines, and how do you choose the right SLO? Because reliability past a certain point is invisible to users while remaining extremely expensive — each nine costs roughly an order of magnitude more, and users literally cannot perceive the difference above their own experience threshold. If your users access the service over mobile connections that are themselves only ~99% reliable, then a 99.99% or 99.999% backend is entirely hidden by their own connection's failures — you'd be spending 10-100× more for zero user-perceptible benefit, money that could fund features. You choose the SLO by asking where reliability stops mattering to *users*: an internal admin tool might be fine at 99%, a core purchase flow might justify 99.95%, and the deciding factor is the actual cost of unavailability to users and the business, not a reflexive desire for more nines. The right SLO is the point where making it better stops improving the user experience.

Further reading