An SLO (service level objective) is a target value for how reliable a service should be, measured by a service level indicator (SLI) over a time window, for example 99.9% of checkout requests succeed within 300 ms over 30 days. The gap between the SLO and 100% is the error budget.
Key takeaways
- An SLI is a measurement (good events divided by valid events); an SLO is the target for that measurement over a window; an SLA is a contract with consequences.
- The error budget is 1 minus the SLO. At 99.9% over 30 days you may spend 43.2 minutes of full downtime or 0.1% of requests.
- Alert on error budget burn rate with multiple windows instead of on raw thresholds; this cuts noise and catches both fast and slow burns.
- Good SLOs are few, user-centric, owned by a team and tied to an agreed policy for what happens when the budget runs out.
What is an SLO?
A service level objective (SLO) is an explicit, measurable reliability target for a service. It combines three things: a service level indicator (SLI) that measures some aspect of user experience, a target such as 99.9%, and a time window such as a rolling 30 days. A complete SLO reads like a sentence: "99.9% of HTTP requests to the checkout API complete successfully in under 300 ms, measured over a rolling 28-day window."
The concept was popularised by Google's Site Reliability Engineering book, which defines an SLI as a carefully defined quantitative measure of some aspect of the level of service provided, and an SLO as a target value or range of values for a service level that is measured by an SLI. The point of an SLO is not to describe perfection. It is to state how much unreliability users will tolerate, so that engineering teams can make deliberate trade-offs between shipping features and investing in stability.
SLI vs SLO vs SLA
The three terms are often mixed up. They are related but serve different audiences.
| Term | What it is | Example | Who cares |
|---|---|---|---|
| SLI (indicator) | A measurement, usually a ratio of good events to valid events | Share of requests with status below 500 and latency under 300 ms | Engineers, SREs |
| SLO (objective) | An internal target for the SLI over a window | SLI of at least 99.9% over 30 days | Engineering and product teams |
| SLA (agreement) | A contract with customers, with penalties if missed | 99.5% monthly availability or service credits apply | Customers, legal, sales |
A rule of thumb: the SLO should be stricter than the SLA. If your SLA promises 99.5%, an internal SLO of 99.9% gives you an early warning long before contractual penalties kick in.
How to choose good SLIs
The most useful SLIs are expressed as a ratio: SLI = good events / valid events × 100%. This form works for almost any service and makes the error budget easy to reason about. Typical SLI types by service category:
- Request-driven services (APIs, web frontends): availability (share of non-error responses) and latency (share of requests faster than a threshold).
- Data pipelines and batch jobs: freshness (share of data updated within N minutes), correctness and coverage.
- Storage systems: durability and read or write latency.
- User journeys: completion rate of a multi-step flow, such as login or checkout, measured with real user monitoring or synthetic checks.
Measure as close to the user as is practical. A load balancer or edge proxy sees failed connections that the application never logs; real user monitoring sees client-side failures that no server sees. Prefer percentile-based latency thresholds ("99% of requests under 300 ms") over averages, because averages hide the tail that users actually feel. Define clearly what counts as a valid event: health checks, synthetic probes and requests rejected with 4xx because of client errors are usually excluded.
Error budgets: how to calculate them
The error budget is the amount of unreliability an SLO allows: error budget = 1 − SLO. For a 99.9% SLO the error budget is 0.1%. You can express it in two ways.
Time-based error budget
Multiply the window by the error budget. A 30-day window has 43,200 minutes, so:
| SLO | Error budget | Allowed downtime per 30 days | Per year |
|---|---|---|---|
| 99% | 1% | 7 h 12 min | 3.65 days |
| 99.5% | 0.5% | 3 h 36 min | 1.83 days |
| 99.9% | 0.1% | 43.2 min | 8.76 h |
| 99.95% | 0.05% | 21.6 min | 4.38 h |
| 99.99% | 0.01% | 4.32 min | 52.6 min |
Request-based error budget
For request-driven services an event-based budget is more accurate. If the checkout API handles 20 million requests in 30 days with a 99.9% SLO, the budget is 20,000,000 × 0.001 = 20,000 failed or slow requests. If 8,000 have already failed on day 10, you have consumed 40% of the budget in a third of the window, which is slightly faster than a linear pace.
Each extra "nine" cuts the budget by a factor of ten and typically raises cost and engineering effort considerably. Also remember that reliability compounds: a service that synchronously depends on three components, each at 99.9%, cannot be better than roughly 99.7% unless it adds redundancy or graceful degradation.
Burn rate alerting
The burn rate is how fast you consume the error budget relative to the window: burn rate = observed error rate / (1 − SLO). A burn rate of 1 spends exactly the full budget over the window. A burn rate of 14.4 on a 30-day, 99.9% SLO means an error rate of 1.44%, and it would exhaust the entire monthly budget in about 50 hours.
The Google SRE Workbook recommends multi-window, multi-burn-rate alerts instead of static thresholds:
- Page when 2% of the budget is consumed in 1 hour (burn rate 14.4), confirmed by a 5-minute short window.
- Page when 5% of the budget is consumed in 6 hours (burn rate 6), confirmed by a 30-minute short window.
- Ticket when 10% of the budget is consumed in 3 days (burn rate 1), confirmed by a 6-hour short window.
The long window ensures the problem is significant; the short window ensures it is still happening, so the alert resets quickly after recovery. This approach gives high precision and good recall: brief blips do not wake anyone up, while sustained degradation does.
Error budget policy and governance
An SLO without consequences is just a dashboard. An error budget policy is a written agreement between engineering, product and operations about what happens at different budget levels. A common policy looks like this:
- Budget healthy: ship features at normal velocity, run chaos experiments, do risky migrations.
- Budget below 25%: require extra review for risky changes and prioritise known reliability issues.
- Budget exhausted: freeze non-critical releases until the SLI recovers, and dedicate capacity to postmortem action items.
The policy turns reliability from an argument into a data-driven decision. It also protects teams from over-investing: if you consistently end the window with most of the budget unused, the SLO may be too loose or you can afford to move faster.
Example: a complete SLO specification
Writing SLOs down in a structured, version-controlled format makes them reviewable like code. A minimal specification for a checkout service could look like this:
service: checkout
owner: team-payments
slo:
name: checkout-availability-latency
sli:
good: spans where status != error and duration < 300ms
valid: spans where http.route == "/api/checkout" and not synthetic
objective: 99.9
window: 30d rolling
alerting:
page: burn_rate >= 14.4 over 1h and 5m
page: burn_rate >= 6 over 6h and 30m
ticket: burn_rate >= 1 over 3d and 6h
Note how latency and availability are combined into one SLI: a request that succeeds after four seconds is not "good" from the user's perspective. Some teams prefer separate SLOs for each, often with two latency thresholds (for example 90% under 100 ms and 99% under 500 ms) to capture both typical and tail experience.
Best practices and common pitfalls
- Start with few SLOs. Two to four per critical user journey is enough. Dozens of SLOs dilute attention.
- Base targets on history and user expectations, not wishes. Look at the last 90 days of SLI data, then set a target users would notice falling below.
- Do not aim for 100%. Users cannot tell the difference between 99.999% and 100% because their own network and devices are less reliable than that, while the cost is enormous.
- Avoid averages and resource metrics as SLIs. CPU at 90% is not a user problem; failed checkouts are.
- Prefer rolling windows for operational alerting and calendar windows for reporting to stakeholders.
- Assign an owner to every SLO and review targets quarterly as traffic, architecture and expectations change.
- Exclude planned maintenance carefully, or better, design maintenance so it does not burn budget at all.
How Obseria helps with SLOs
SLOs are included in every Obseria plan. You define SLIs on any signal Obseria collects, including OpenTelemetry spans, metrics, logs, real user monitoring events and synthetic check results, either in the UI or with an OQL query such as fetch spans | filter service == "checkout" | summarize good = countIf(status != "error" and duration < 300ms), total = count(). Obseria tracks error budget consumption, evaluates multi-window burn rate alerts and links every budget burn to the traces, deployments and topology changes that caused it, so Obseria Intelligence can start a root-cause investigation with a chain of evidence the moment budget is at risk.