Be Software Architecture Wise
Be Wise Apps

Leer en español · Lire en français · Auf Deutsch lesen

Section 9.5 of 9.8 · Intermediate · 24 min read

SLIs, SLOs, SLAs and error budgets

Video lesson

5 min · narrated, with captions
Listen only (audio)
Read the transcript

Welcome to Section nine point five. How reliable should a service be? This lesson turns that question into numbers that engineers and product owners can agree on.

Imagine a bus company that promises nearly all buses on time. To make that useful, it must say what counts as on time: within two minutes. It must say how it measures it: at each stop. And what nearly all means: ninety nine in every hundred over a month. If it misses that, the timetable team stops trying new routes and fixes punctuality first. Perfection is impossible and very expensive. So the one late bus in a hundred is an allowance to spend on roadworks and new routes. Software reliability works exactly like this.

A service level indicator, or SLI, is a measurement of what users receive. The best form is a ratio: good events divided by valid events. For example, the proportion of checkout requests that succeed within eight hundred milliseconds. A service level objective, or SLO, is a target for that indicator over a stated window, such as ninety nine point nine per cent over a rolling twenty eight days. A service level agreement, or SLA, is a contract with customers that names consequences, usually service credits. Many services have SLOs, but no SLA. The idea that ties them together is the error budget. With a target of ninety nine point nine per cent, one event in a thousand may be bad without anyone having failed. That's the room to release features and take risks.

Here are the three terms on one scale, for checkout availability. The SLO is the internal target, ninety nine point nine per cent. The SLA, a contract with partners, is set looser, at ninety nine point five. Above the SLO, the service is within its budget. This month's SLI is ninety nine point nine four per cent. Below the SLO, the target is missed, and the error budget policy applies. Only below the SLA are service credits owed. Never set the SLO equal to the SLA. You'd learn about trouble only when you already owe money.

An SLI is only as useful as its closeness to what users experience. Services that answer requests need availability, latency and sometimes quality. Data pipelines need freshness, correctness and coverage. Storage adds durability. Write latency as a proportion, not an average: ninety nine per cent of menu requests faster than three hundred milliseconds. And measure close to the user. Inside the application server, you miss requests that never reached it.

Let's count a budget. The food delivery order API has an SLO of ninety nine point nine per cent over thirty days. So the budget is nought point one per cent. In time, that's forty three point two minutes of total outage. In requests, with about three million a month, it's three thousand bad requests. Now a bad deployment at three in the afternoon lasts twelve minutes. At eight hundred requests a minute, with forty per cent failing, that's three thousand eight hundred and forty bad requests. That's more than the whole budget. One incident has used up the month. The same incident at three in the morning, with fifty requests a minute, costs only two hundred and forty: eight per cent of the budget. Request-based budgets weight failures by how many users they hit.

A target is a business decision. Aiming for a hundred per cent is wrong for almost everything. It leaves no budget for change, costs a fortune and can't be achieved anyway. An error budget policy says what happens when the budget runs out. In the example from Google's Site Reliability Workbook, all changes stop except urgent and security fixes, until the service is back within its SLO. Its value lies in being agreed in advance, so a freeze is a pre-agreed rule, not a fight. And a team that never spends its budget is probably too cautious. It could ship faster or run more experiments.

How should you alert? Watch the burn rate: how fast the budget is being spent. A burn rate of one, the dashed line, uses the budget up exactly at the end of the thirty days. A fast burn spends a large share in hours. Here, thirty per cent went in about three hours. That should wake someone up. A slow burn, here a rate of about two for five days, belongs in a ticket. The Workbook's default for a ninety nine point nine per cent SLO pages if two per cent of the budget goes in one hour, a burn rate of fourteen point four, or five per cent in six hours. A complete outage pages in under a minute.

The full section works through the burn rate arithmetic and common mistakes. Next, in Section nine point six, we look at logs, metrics and traces. See you there.

What you need to know

Three terms, one idea

Chapter 2 introduced availability targets and the nines (Section 2.5) and showed that 99.9% over 30 days leaves 43.2 minutes. This section turns that arithmetic into an operating discipline. The vocabulary comes from Google's Site Reliability Engineering book (Beyer, Jones, Petoff and Murphy, O'Reilly, 2016) and its companion, The Site Reliability Workbook (2018), and is now used far beyond Google.

A service level indicator (SLI) is a carefully defined, quantitative measure of some aspect of the service users receive. The most useful form is a ratio: good events divided by valid events. The proportion of checkout requests that return a successful response within 800 ms, measured at the load balancer is an SLI. It ranges from 0% (nothing works) to 100% (nothing is broken), and the ratio form means every SLI can be read, compared and alerted on the same way.

A service level objective (SLO) is a target for an SLI over a stated window: 99.9% of checkout requests are good, measured over a rolling 28 days. It is an internal promise that the team, the product owner and the people who depend on the service agree to. A service level agreement (SLA) is a contract with customers that names consequences, usually service credits, if a level is missed. Many services have SLOs but no SLA; internal platforms almost never have SLAs at all.

The idea that ties the three together is the error budget. If the target is 99.9%, then 0.1% of events may be bad without anyone having failed. That 0.1% is not waste; it is the room the team has to take risks: releasing features, running migrations, experimenting with configuration. The budget turns an argument about feelings (is the service reliable enough?) into an argument about numbers (have we spent our budget?), and gives product and engineering a shared rule for when to move fast and when to slow down.

SLI, SLO and SLA on one scale

On one availability scale from 99.0% to 100%, the SLA threshold at 99.5% sits below the SLO at 99.9%, and this month's measured SLI of 99.94% sits above the SLOCheckout availability, rolling 28 days (scale not linear)SLA missed:service credits owedSLO missed:budget policy appliesWithinbudget99.0%99.5%99.9%100%SLI this month: 99.94%SLA: 99.5%contract with partnersSLO: 99.9%internal target
The SLI is the measurement, the SLO the internal target and the SLA a looser contractual floor; the gap between SLO and SLA is the warning zone.

Choosing good SLIs

An SLI is only as useful as its closeness to what users experience. The Workbook offers a short menu that covers most services. Request-driven services (APIs, web pages) need availability (the proportion of valid requests served successfully), latency (the proportion served faster than a threshold) and sometimes quality (the proportion served without degradation, such as a menu shown without personalised recommendations because that dependency was down). Data pipelines need freshness (the proportion of data updated more recently than a threshold), correctness (the proportion of output that is right) and coverage (the proportion of input processed). Storage systems add durability (the proportion of written data that can still be read).

Latency SLIs are written as proportions, not averages: 99% of menu requests faster than 300 ms. This connects directly to the percentiles of Section 2.4: saying 99% of requests must be under 300 ms is the same as saying p99 must be under 300 ms, but the proportion form adds up cleanly across time and servers (count the good ones and the valid ones), while percentiles do not. It is common to set two latency thresholds, for example 90% under 200 ms and 99% under 800 ms, to capture both typical and tail experience.

Where you measure matters as much as what you measure. The Workbook separates the SLI specification (the user-relevant outcome, such as orders placed successfully) from the SLI implementation (how you count it: server logs, load balancer metrics, synthetic probes or instrumentation in the mobile app). Measuring inside the application server misses requests that never reached it because DNS, the content delivery network or the load balancer failed. Measuring in the client sees everything but includes users' bad mobile connections and arrives late. Most teams start with load balancer metrics, which are cheap and close to the edge, and add synthetic probes for low-traffic paths.

Define what counts as valid and what counts as good precisely, because the edge cases decide whether the number means anything. Is a 404 for a mistyped URL bad? Usually not: it is a correct answer. Is a 429 rate-limit response bad? It depends on whether the client was within its agreed quota. Are health checks and load tests valid events? No; exclude them, or they dilute the ratio. Write these rules down next to the SLO.

SLIs for the running examples

JourneySLI typeSLI specification (good / valid)Example SLO
Food delivery: browse menusLatencyMenu requests answered in under 300 ms / all valid menu requests99% over 28 days
Food delivery: place orderAvailabilityOrder requests answered with success or a correct business refusal / all valid order requests99.9% over 28 days
Food delivery: courier locationFreshnessMap views whose courier position is under 30 s old / all map views99% over 28 days
Food delivery: restaurant payoutsCorrectnessPayout batches reconciled without discrepancy / all payout batches99.99% over a quarter
Ticketing: on-sale checkoutLatency and availabilitySeat holds confirmed within 2 s / all hold attempts by admitted fans99.5% during each on-sale
Ticketing: e-ticket deliveryFreshnessTickets in the fan's app within 5 minutes of payment / all paid orders99.9% over 28 days

Setting the target

A target is a business decision, not a technical one. The cost of each extra nine rises steeply, while users stop noticing improvements beyond some point because their own phone network, Wi-Fi and devices fail more often than that. Google's SRE book makes the point bluntly: aiming for 100% is wrong for almost everything, because it leaves no budget for change, costs a fortune and cannot be achieved anyway. A 100% target also turns every single failure into a policy breach, which teaches people to ignore the SLO.

Good starting points are past performance (what did the service achieve over the last quarter, and were users happy?), the targets of the services you depend on (you cannot promise 99.99% on top of a 99.9% database, as Section 6.1 showed for chains), and the business cost of unreliability. For the food-delivery platform, failed orders at lunchtime cost revenue and customer trust, so 99.9% on order placement is defensible; courier position updates are less critical and 99% is enough. Begin a little below current performance, so the team is not instantly in breach, and tighten later with evidence.

Choose the window deliberately. A rolling window such as the last 28 days matches how users remember outages (they do not forget on the first of the month), and 28 days contains exactly four of each weekday, which keeps weekly patterns fair. Calendar months suit reporting and contracts. Event-based services such as a ticket on-sale may need an SLO per event, because an hour of failure during the on-sale matters far more than a quiet week.

Error budgets in numbers

The error budget can be counted in time or in events. Time-based budgets suit services that are either up or down; request-based budgets are fairer for services with uneven traffic, because an outage at 03:00 affects fewer users than one at noon.

Worked example

Worked example: the order-placement budget

The food-delivery platform's order API has an SLO of 99.9% good requests over 30 days. It handles about 3 million valid order requests in that period, heavily concentrated at lunch and dinner.

Budget as a fraction1 - 0.999 = 0.001, or 0.1%
Budget in time0.001 × 30 days × 1,440 minutes = 43.2 minutes of total outage
Budget in requests0.001 × 3,000,000 = 3,000 bad requests
Incident 1: bad deployment at 15:0012 minutes × 800 requests per minute = 9,600 requests; 40% failed = 3,840 bad requests
Result3,840 is more than the whole 3,000-request budget: one incident exhausts the month
Same incident at 03:0012 × 50 requests per minute × 0.4 = 240 bad requests, 8% of the budget

Request-based budgets weight failures by how many users they hit, which is why the same 12 minutes can cost 8% or more than 100% of the budget.

The time-based view (43.2 minutes) would have scored both incidents identically, at 12 × 0.4 = 4.8 minutes of equivalent outage, about 11% of the budget.

Error budget policies

A budget means nothing unless something happens when it runs out. An error budget policy is a short document, agreed in advance by engineering, product and leadership, that says what the team will do. The example policy in the Workbook measures the budget over a trailing four weeks; if the service exceeds its budget, all changes and releases stop except urgent fixes (P0 issues) and security fixes until the service is back within its SLO. It also requires a postmortem with at least one top-priority action item whenever a single incident consumes more than 20% of the four-week budget, and escalates disagreements to the chief technology officer.

The value of a policy lies in being agreed before it bites. In the middle of a release crunch, nobody wants to freeze; with a signed policy, the freeze is a pre-agreed rule rather than a fight between an SRE and a product manager. Good policies also say what does not count against the team: a company-wide network outage, a dependency that is itself frozen, or traffic outside the SLO's scope such as a load test.

Practitioners disagree about how mechanical the policy should be. Some teams apply it strictly, because exceptions erode trust in the whole system. Others treat the budget as information for a conversation, arguing that a hard freeze can delay the very fixes that would restore reliability. A middle path is common: freeze risky feature releases automatically, keep shipping reliability fixes, and allow a named executive to grant documented exceptions. The opposite case also matters: a team that never spends its budget is probably too cautious and could ship faster, run more experiments or lower its costs.

Burn rate and alerting on SLOs

Alerting on raw error rates (page if more than 1% of requests fail for 5 minutes) is noisy: short blips page people at night for problems that would never threaten the SLO, while a steady 0.5% failure rate can quietly use up the month without ever crossing the threshold. The Workbook's answer is to alert on the burn rate: how fast the budget is being spent compared with the rate that would use it up exactly at the end of the window.

Burn rate = observed error ratio / allowed error ratio. With a 99.9% SLO the allowed ratio is 0.1%, so an error ratio of 0.1% is a burn rate of 1 (the budget lasts exactly the window), 1% is a burn rate of 10, and 100% (a full outage) is a burn rate of 1,000. The fraction of the window's budget spent during an alerting window is burn rate x alerting window / SLO window. For a 30-day (720-hour) window, a burn rate of 14.4 sustained for one hour spends 14.4 × 1 / 720 = 0.02, that is 2% of the month's budget; at that rate the whole budget would be gone in 720 / 14.4 = 50 hours.

The Workbook recommends a multiwindow, multi-burn-rate alert as a sensible default for a 99.9% SLO: page if 2% of the budget is spent in one hour (burn rate 14.4) or 5% in six hours (burn rate 6), and open a ticket if 10% is spent in three days (burn rate 1). Each condition must hold over a long window and a short one, with the short window one twelfth of the long (5 minutes, 30 minutes and 6 hours respectively). The long window ensures the problem is significant; the short window ensures it is still happening, so the alert stops firing within minutes of a fix instead of staying red for an hour.

Fast and slow burns

Error budget remaining over a 30-day window: a steady burn would reach zero on day 30; the actual line drops sharply during an incident on day 9 and declines faster than steady between days 20 and 25100%50%0%day 0day 10day 20day 30Days into the 30-day windowactual budget remainingsteady burn (rate 1)Fast burn: page30% spent in about 3 hoursSlow burn: ticketrate about 2 for 5 days13% leftError budget remaining
A fast burn spends a large share of the budget in hours and should wake someone; a slow burn spends it over days and belongs in a ticket.
SLO = 0.999                 # 99.9% of requests good
PERIOD_H = 30 * 24          # 720-hour SLO window

def burn_rate(bad, total, slo=SLO):
    """Observed error ratio divided by the ratio the SLO allows."""
    if total == 0:
        return 0.0
    return (bad / total) / (1 - slo)

def budget_spent(rate, window_h, period_h=PERIOD_H):
    """Fraction of the whole window's budget used in window_h hours."""
    return rate * window_h / period_h

def page(w1h, w5m, w6h, w30m):
    """Each argument is (bad, total) for that window."""
    fast = burn_rate(*w1h) >= 14.4 and burn_rate(*w5m) >= 14.4
    slow = burn_rate(*w6h) >= 6 and burn_rate(*w30m) >= 6
    return fast or slow

print(round(burn_rate(bad=288, total=20_000), 1))   # 14.4
print(budget_spent(14.4, window_h=1))               # 0.02, i.e. 2%
Burn rate, budget spent and a two-window paging rule. In production the same logic is written as alerting rules in the monitoring system (for example Prometheus recording and alerting rules).

The thresholds also fix detection time. If the order API fails completely (error ratio 100%, burn rate 1,000), the one-hour error ratio crosses 1.44% after 0.0144 × 60 = about 0.9 minutes, so the page fires in under a minute. If 2% of requests fail (burn rate 20), the one-hour ratio reaches 1.44% after 0.72 × 60 = about 43 minutes. Severe problems page fast; mild ones page only if they persist, which is exactly the behaviour people want at three in the morning.

Low-traffic services break this arithmetic: with 10 requests an hour, one failure is a 10% error ratio and a burn rate of 100. The Workbook's remedies are synthetic traffic to add signal, grouping related low-traffic services under one SLO, making single failures matter less through retries and fallbacks, or accepting a longer window. For the ticketing system, which is almost idle between on-sales and then extremely busy, per-event SLOs with burn-rate alerts during the event window work better than a monthly figure.

SLAs and service credits

An SLA moves the target from engineering into contract law. It defines the service covered, how availability is measured, exclusions (scheduled maintenance, customer misuse, force majeure), the remedy and how a customer claims it. The usual remedy is a service credit: a percentage of the monthly fee returned, tiered by how badly the level was missed. Credits are typically small compared with the customer's actual loss, which is why SLAs are better read as a signal of the provider's confidence than as insurance; customers whose losses would be large need their own resilience, not a bigger credit.

Consider an illustrative SLA the food-delivery platform might offer restaurant partners for its order-intake API: 99.5% monthly availability, with a 10% credit on that month's platform fee below 99.5% and 25% below 99.0%. The internal SLO is 99.9%. The gap between them is deliberate: the team should exhaust its SLO budget, apply its policy and recover long before the contract is at risk. Never set the SLO equal to the SLA; you would learn about trouble only when you already owe money.

Two architectural consequences follow. First, an SLA can only be honest if you know the SLAs of your own dependencies (cloud provider, payment processor, map provider) and how they combine. Second, SLAs need evidence: the measurement method in the contract must be one you can produce from your own telemetry, which is a requirement on the observability design.

Common mistakes

Too many SLOs. A service with thirty SLOs has none, because nobody can reason about them or act on them. Start with two or three per critical user journey: usually one availability and one or two latency SLOs. Measuring the wrong thing. CPU utilisation, queue depth and replica lag are useful causes to watch, but they are not SLIs, because users do not experience them directly. Measuring in the wrong place. Server-side success rates look perfect while the CDN returns errors. Averaging. An average latency SLO hides the slow tail that users complain about.

Targets without consequences. An SLO with no budget policy and no burn-rate alerts is a dashboard decoration. Targets set by engineers alone. The product owner must agree, because the SLO trades features for reliability. Never revising. Review SLOs every quarter or two: if users complain while the SLO is green, the SLI or the target is wrong; if the budget is never touched, the target may be too loose or the team too cautious. One SLO for very different journeys. Lumping menu browsing and payment into one ratio lets plentiful cheap requests hide failures in the scarce, valuable ones.

SLOs connect to the rest of this chapter. Burn-rate alerts are the symptom-based alerts recommended in observability; budget-burning incidents feed post-incident reviews; and an SLO's response measure is a natural fitness function for the architecture.

Check your understanding

Why is an SLI usually written as good events divided by valid events?

Because the ratio always lies between 0% and 100%, adds up cleanly across servers and time by counting, and lets every SLI be read, compared and turned into an error budget the same way.

A 99.9% SLO over 30 days sees a burn rate of 6 for six hours. What fraction of the budget is spent?

6 × 6 / 720 = 0.05, so 5% of the 30-day budget.

Why should an SLA be looser than the internal SLO?

So that the team detects and responds to a spent error budget well before the contract is breached and service credits become payable.

What does the short window in a multiwindow alert add?

It confirms the problem is still happening, so the alert resets within minutes of a fix instead of staying active for the whole long window.

Next · 9.6ObservabilityHow to see inside a running distributed system: structured logs, metric types and histograms, RED, USE and the golden signals, distributed tracing with W3C Trace Context and OpenTelemetry, cardinality and symptom-based alerting.Continue →

Sources and further reading

Have a question about this section? ArchitectBot, the course’s AI study assistant, answers from the course first.

Ask: “Our food-delivery API has no SLOs yet. Which two or three SLIs should we start with, and how do we pick a target the product team will accept?”