Filter concepts by levelShowing all levels.

System Design · Section 8

SLIs, SLOs, SLAs and Error Budgets

Level
intermediate
Read
16 min
Concepts
3

The three-layer vocabulary of service commitments — SLI (the measured indicator), SLO (the internal target), and SLA (the externally committed, consequence-bearing contract) — grounded in four SLIs worth tracking (success rate, p95 latency, queue age, data freshness), and connected to shipping speed through the error budget: the allowed room for failure an SLO permits, spent by every incident, and used to decide whether it is safe to ship faster or time to freeze and stabilize.

System Design overview

What is true here

  1. SLI = the measured value; SLO = the internal target for it; SLA = the external, consequence-bearing version, set looser than the SLO for buffer.
  2. Common SLIs: request success rate, p95 latency, queue age, data freshness — track more than one, since each catches a different failure mode.
  3. Error budget = (1 − SLO) × time window — a 99.9% monthly SLO permits about 43.2 minutes of failure.
  4. A healthy remaining error budget justifies faster, riskier releases; a nearly exhausted one justifies a release freeze and a focus on stability.

What you will be able to do

  • Distinguish SLI, SLO and SLA and explain why the SLO is set stricter than the SLA
  • Name at least four common SLIs and the distinct failure mode each one catches
  • Compute an error budget from an SLO and a time window
  • Explain how a remaining error budget should influence release velocity and operational priorities

The vocabulary and the budget

The three-layer SLI/SLO/SLA vocabulary, concrete SLIs worth tracking, and the error budget that connects them to release decisions.

SLI, SLO and SLA

corebeginner

An SLI is the actual measured number (e.g. 99.95% of requests succeeded). An SLO is the internal target for that number (e.g. "keep it above 99.9%"). An SLA is the externally committed version of that target, usually with a financial or contractual consequence for missing it.

Think of it as

Think of a school grading system: the SLI is the student's actual measured score on a test. The SLO is the target the student sets for themselves internally ("I want to keep my average above 90%"). The SLA is the version of that promised to someone else with consequences attached — a scholarship contract that says "maintain a 90% average or lose funding." The SLI is a fact; the SLO is a goal; the SLA is a promise with teeth.

text
SLI = the measured value            (fact)
SLO = the internal target for it    (goal)
SLA = the external, contractual SLO (promise + penalty)

SLA target  <  SLO target  <=  actual SLI (healthy state)

What we're doing: Trace one metric through all three layers and show why the SLA is set looser than the SLO.

sli-slo-sla-definitions.txttext
Metric: request success rate.

  SLI: measured at 99.93% this month.
  SLO: internal target of 99.9% — engineering treats
       anything below this as needing attention.
  SLA: 99.5% committed to customers, with a service
       credit owed if breached.

Order: SLA (99.5%) < SLO (99.9%) <= SLI (99.93%).

The gap between SLO and SLA is deliberate buffer —
an SLO breach is a warning sign well before it
becomes an SLA breach with real financial cost.
3
The SLI is simply what was actually observed — no target or promise attached yet.
5
The SLO is stricter than the SLA on purpose, so engineering gets an internal warning before a customer-facing breach.
9
Ordering the three values makes the buffer visible: there is room to miss the SLO several times before ever breaching the SLA.

Why this works: Setting the SLO tighter than the SLA is what turns "we breached our contract" from a surprise into something engineering saw coming and had time to react to.

Setting the SLO equal to the SLA, with no buffer

Wrong

text
SLO: 99.5% success rate.
SLA: 99.5% uptime committed to customers.
(identical thresholds, no warning margin)

Better

text
SLO: 99.9% success rate (internal target).
SLA: 99.5% uptime committed to customers.
(SLO breach gives engineering advance warning
before the SLA is ever at risk)

What you see: The first sign of trouble engineering sees is the same moment the customer-facing SLA is breached — there was no earlier internal threshold to react to.

Why: An SLO with no buffer over the SLA provides no early warning — by the time it is breached, the SLA is breached too. The gap between the two is what gives engineering time to respond before a contractual or financial consequence hits.

SLA < SLO <= SLI — buffer at every layer

SLI: 99.93%

the measured fact, this month

SLO: 99.9%

internal target — engineering's early warning

SLA: 99.5%

external contract, with a service credit if breached

  1. SLI: 99.93% — the measured fact, this month
  2. SLO: 99.9% — internal target — engineering's early warning
  3. SLA: 99.5% — external contract, with a service credit if breached

SLI vs SLO vs SLA

SLI vs SLO vs SLA
TermWhat it isAudienceExample
SLIthe measured numberengineering99.95% success rate, measured this week
SLOthe internal target for that numberengineering, productkeep success rate ≥ 99.9%
SLAthe externally committed version, with consequencescustomers, legal99.5% uptime or a service credit

Together

text
SLI (this week):  99.94% of requests succeeded
SLO (internal):    99.9% success rate target
SLA (external):    99.5% uptime committed to customers,
                    with a service credit if missed

99.94% (SLI) beats the SLO (99.9%), which beats
the SLA (99.5%) — the SLA has the most buffer.

Remember: SLI = the measured fact. SLO = the internal target. SLA = the external, consequence-bearing promise. SLO is set stricter than SLA.

See also: sli examples · error budgets

Common SLIs: success rate, latency, queue age, freshness

standardbeginner

Four SLIs cover most services: request success rate (did it work), p95 latency (was it fast enough for most users), queue age (is a background system keeping up), and data freshness (is what a reader sees current enough to be useful).

Think of it as

Each SLI targets a different way a service can fail its users even while technically "running." Success rate catches outright errors. Latency catches a service that works but is too slow to be useful. Queue age catches an asynchronous system silently falling behind. Data freshness catches a read-heavy system serving correct-looking but stale data. A service usually needs more than one SLI, because each one is blind to failures the others catch.

text
success rate  = non-error responses / total responses
p95 latency   = the latency value at the 95th percentile
queue age     = now - enqueued_time(oldest unprocessed item)
data freshness = now - last_updated_time(the data being read)

What we're doing: Show a service that looks healthy on one SLI while failing badly on another, to justify tracking more than one.

sli-examples.txttext
A notification service, checked against all four SLIs:

  Success rate:   99.98%  -> looks excellent
  p95 latency:    120ms   -> looks excellent
  Queue age:      45 minutes -> a real problem
  Data freshness: n/a for this service

Success rate and latency both look great, because
requests that ENQUEUE a notification succeed fast.
But the queue itself is 45 minutes behind, so users
are not receiving notifications for 45 minutes —
a real, ongoing failure neither of the first two
SLIs would have caught.
3
Success rate and latency both measure the API call that enqueues work, not whether that work actually completed.
8
Queue age is the SLI that actually reveals this failure — the other two stay green throughout the incident.

Why this works: A single SLI is only ever a partial view of "is this service actually working." Choosing SLIs that cover different failure modes is what prevents a real ongoing problem from hiding behind two green dashboards.

Tracking only request success rate for an asynchronous system

Wrong

text
SLO: "99.9% of enqueue requests succeed."
(nothing measures whether enqueued work is
ever actually processed, or how quickly)

Better

text
SLOs: "99.9% of enqueue requests succeed" AND
"queue age stays under 60 seconds at p95."

What you see: Every dashboard is green — requests succeed, latency is low — while a background queue silently backs up for hours and users never receive what they were promised.

Why: Request success rate for an async system only confirms the work was accepted, not that it was completed. Queue age is the SLI that actually measures whether the asynchronous half of the system is keeping up.

Three green tiles, one ongoing outage

A notification service during a 45-minute backlog. Success rate and latency measure the call that accepts the work, not the work.

  • Four dashboard tiles for a notification service.
  • Success rate 99.98 percent — green, looks excellent.
  • p95 latency 120ms — green, looks excellent.
  • Queue age 45 minutes — red, the real failure.
  • Data freshness not applicable for this service.
  • Below: the first two measure the call that enqueues work, and neither measures whether the work was ever done.

Common SLIs

Common SLIs
SLIWhat it measuresCatches
Request success rate% of requests returning a non-error responseoutright failures, 5xx errors, crashes
p95 latencythe latency 95% of requests are at or belowa service that works but is too slow
Queue agehow long the oldest unprocessed item has waiteda background worker falling behind
Data freshnesshow old the data being served isstale reads from a lagging replica or cache

Together

text
A checkout service, four SLIs measured together:

  Success rate:  99.96% of checkout requests succeed
  p95 latency:   340ms
  Queue age:     oldest unprocessed payment webhook: 4s
  Data freshness: inventory count reflects orders from
                  the last 2 seconds

Remember: Success rate catches errors, p95 latency catches slowness, queue age catches a falling-behind background system, freshness catches stale reads — track more than one.

See also: sli slo sla definitions · error budgets

Error budgets and release velocity

coreintermediate

An error budget is the amount of failure an SLO allows — 100% minus the SLO, over a time window. Spending it fast (a bad release, an incident) means slowing down and stabilizing; having budget left means it is safe to ship faster and take more risk.

Think of it as

A 99.9% monthly SLO permits about 43.2 minutes of failure a month — that is the error budget, a spendable resource like a monthly allowance. Every outage, failed deploy, or degraded period spends from it. When the budget is healthy, the team can ship features aggressively — the SLO has room to absorb some risk. When the budget is nearly exhausted, the same team should slow down, freeze risky releases, and focus on stability, because the next incident would breach the SLO outright. The budget turns "be careful" into a number everyone can check.

text
error budget = (1 - SLO) × time_window

remaining budget = error budget - time_spent_out_of_SLO

remaining budget low  -> freeze risky releases, focus on stability
remaining budget high -> safe to ship faster, take more risk

What we're doing: Track an error budget across a month of incidents and show the policy decision it drives at the end.

error-budgets.txttext
SLO: 99.9% monthly -> budget ≈ 43.2 minutes.

  Week 1: no incidents.            remaining: 43.2 min
  Week 2: 20-minute outage.        remaining: 23.2 min
  Week 3: 18-minute outage.        remaining:  5.2 min
  Week 4: budget nearly gone.

Policy at week 4: freeze non-critical releases,
prioritize the reliability work that caused weeks
2 and 3's outages, until the budget resets next month.
4
The budget starts full at the beginning of the SLO window.
6
Each incident subtracts directly from the remaining budget — a running, checkable number, not a vague sense of "things have been rough lately."
9
A budget that is nearly exhausted is what justifies a release freeze — not a subjective call, but a number crossing a threshold.

Why this works: An error budget converts "should we slow down and stabilize, or is it safe to ship the next feature" from a debate into a number both engineering and product can check and agree on.

Treating 100% uptime as the goal instead of managing to the budget

Wrong

text
"Every outage is unacceptable — we should
never have any downtime."

Better

text
"Our SLO allows ~43 minutes of downtime a
month. We're well within budget — safe to ship
this week's riskier release."

What you see: Every incident, however small, triggers the same maximum-alarm response, and the team becomes too risk-averse to ship anything — even though the SLO has room to absorb normal operational variance.

Why: An SLO below 100% is a deliberate choice that some failure is acceptable — chasing zero downtime past that point spends effort the error budget says is not needed, and slows down shipping for no reliability gain the SLO actually requires.

A 99.9% SLO's ~43.2-minute monthly budget, spent
  1. Week 1

    No incidents

    remaining: 43.2 min

  2. Week 2

    20-minute outage

    remaining: 23.2 min

  3. Week 3

    18-minute outage

    remaining: 5.2 min

  4. Week 4

    Budget nearly gone

    freeze non-critical releases

  1. Week 1: No incidents — remaining: 43.2 min
  2. Week 2: 20-minute outage — remaining: 23.2 min
  3. Week 3: 18-minute outage — remaining: 5.2 min
  4. Week 4: Budget nearly gone — freeze non-critical releases

Error budget by SLO, 30-day window

Error budget by SLO, 30-day window
SLOMonthly error budgetMeaning
99.9%~43.2 minutesroom for one moderate incident a month
99.95%~21.6 minutesroom for one short incident a month
99.99%~4.3 minutesalmost no room — needs near-zero-downtime deploys

Together

text
SLO: 99.9% monthly.
Budget: 30 days × 24 × 60 × 0.001 ≈ 43.2 minutes.

A 15-minute incident this month spends 15 of the
43.2 minutes:
  remaining = 43.2 - 15 = 28.2 minutes (~65% left)

Remember: Error budget = (1 − SLO) × time window. Spend it on incidents; a healthy remaining budget justifies shipping faster, a low one justifies a release freeze.

See also: sli slo sla definitions · sli examples

Advertisement