SLA vs SLO vs SLI

An SLI (service level indicator) is a measurement, such as the percentage of requests served in under 400 ms. An SLO (service level objective) is the internal target for that measurement, such as 99% of requests under 400 ms over 28 days. An SLA (service level agreement) is a contract with customers that promises a, usually looser, level and states the penalty, typically service credits, if you miss it. Load test thresholds come from the SLO, set with extra margin, not from the SLA.
Definitions with examples
These definitions follow the usage popularized by Google's Site Reliability Engineering book (2016), chapter "Service Level Objectives", which most teams now treat as the reference.
SLI: what you measure
An SLI is a ratio of good events to total events, measured over a window. Good SLIs are defined from the user's point of view and are precise about where they are measured.
- Availability:
non-5xx responses / all responsesat the load balancer, for/api/* - Latency:
requests completed in < 400 ms / all requests, measured server-side at the edge - Freshness:
reads returning data less than 1 minute old / all reads
Expressing latency as "fraction of requests faster than X" rather than "p99 = Y" makes it composable with availability and lets you compute an error budget. The two are equivalent: "99% of requests under 400 ms" is the same statement as "p99 ≤ 400 ms".
SLO: the target
An SLO puts a target and a window on an SLI: "99.9% of API requests return a non-5xx response, measured over a rolling 28 days." It is an internal engineering decision. Missing it should trigger a change in priorities (freeze risky launches, spend time on reliability), not a payment.
SLA: the contract
An SLA is a legal or commercial commitment: "Monthly uptime of at least 99.5%. If missed, the customer receives a 10% service credit." SLAs tend to be simpler (often availability only), looser than the SLO, and defined in terms a customer can verify. Many internal services have SLOs and no SLA at all.
SLA vs SLO vs SLI at a glance
| SLI | SLO | SLA | |
|---|---|---|---|
| What it is | A measurement | A target for a measurement | A contract with consequences |
| Example | % of requests < 400 ms | 99% of requests < 400 ms over 28 days | 99.5% monthly uptime or 10% credit |
| Owned by | Engineering / SRE | Engineering with product | Business, legal, sales |
| Audience | Dashboards, alerts | Teams deciding priorities | Customers |
| Consequence of a miss | None by itself | Error budget spent; slow down releases | Credits, refunds, contract terms |
| Typical strictness | n/a | Tighter than the SLA | Loosest of the three |
| Changes how often | When instrumentation changes | Reviewed quarterly or so | At contract renewal |
| Role in load tests | Same metric definitions in the test | Source of pass/fail thresholds | Rarely used directly |
How the three levels nest
The gap between SLA and SLO is deliberate. If they were the same, every SLO miss would cost money and there would be no warning period. A load test threshold sits above the SLO for a similar reason: a short test at peak load is the best case for a release, and production adds deploys, dependency failures and traffic you did not model.
Error budgets: the SLO turned into a number
The error budget is the amount of failure the SLO allows:
error budget = (1 − SLO) × total events in the window
Worked example: an availability SLO of 99.9% over 30 days allows 0.1% failures. In time, that is 30 × 24 × 60 × 0.001 = 43.2 minutes of full outage. In requests, at 10 million requests per month, it is 10,000 failed requests. The error budget calculator does this for any SLO and window, and also computes burn rates.
Burn rate is how fast you spend the budget relative to plan. A service failing 2% of requests against a 0.1% budget burns at 20x: a 30-day budget gone in 1.5 days. This matters for load tests that run against production. A 10-minute production test that causes 2% errors on 5% of real traffic consumes a measurable slice of the month's budget, so decide in advance how much budget a test may spend.
Turning SLOs into load test thresholds
A load test cannot measure a 28-day SLO directly. It measures a short window at a specific load. Translate each SLO into a threshold on the same SLI, then add margin.
| SLO (production, 28 days) | Equivalent SLI form | Load test threshold at target peak | Why stricter |
|---|---|---|---|
| 99% of requests < 400 ms | p99 ≤ 400 ms | p99 < 320 ms and p95 < 250 ms | ~20% latency headroom for noisy neighbors and deploys |
| 99.9% non-5xx | error rate ≤ 0.1% | error rate < 0.05%, zero 5xx in the smoke stage | Production failures elsewhere also spend the budget |
| 95% of checkouts < 2 s | p95 of checkout flow ≤ 2 s | p95 of full scenario < 1.6 s | Test data is cleaner than real carts |
Three rules make the translation trustworthy:
- Same definitions. If the SLI counts 5xx at the load balancer, the test should count 5xx the same way, and decide explicitly whether 429s and timeouts are errors. Mismatched definitions produce a test that passes while production misses the SLO.
- Same percentile and endpoint scope. A p95 across all endpoints hides a slow checkout behind fast static assets. Set thresholds per critical endpoint or flow.
- Enough samples. A p99 threshold needs about 10,000 steady-state requests to be stable. See how long a load test should run.
In LoadTester, thresholds such as p95 < 400 ms or error rate < 2% can auto-stop a run when breached, which is useful when testing near production. Set them from the stricter test column, not from the SLA. For percentile choice, p95 vs p99 covers the trade-offs, and tail latency explains why services deep in a call graph need tighter targets than the edge.
Example SLO document
A short, versioned SLO file is easier to keep honest than a wiki page. This example is illustrative:
service: orders-api
owner: team-orders
window: 28d rolling
slis:
availability:
good: http responses with status < 500 at the public load balancer
total: all responses for /api/v1/*, excluding /healthz
latency:
good: requests with server-side duration < 400 ms
total: all GET and POST /api/v1/orders* requests
slos:
- sli: availability
objective: 99.9% # budget: ~40 min/28d or 0.1% of requests
- sli: latency
objective: 99% # equivalent to p99 <= 400 ms
error_budget_policy:
- at 50% spent: risky migrations need SRE sign-off
- at 100% spent: feature releases paused until budget recovers
load_test_gates: # derived, stricter than the SLO
peak_rps: 1200
p95_ms: 250
p99_ms: 320
error_rate: 0.05%
sla: 99.5% monthly availability (customer contract v3), no latency term
Keeping the load test gates in the same file means they change when the SLO changes. A load test plan can then reference this file instead of restating numbers.
Where you measure the SLI changes the number
The same request has different latencies depending on where you time it. Pick one measurement point per SLI and use it consistently in dashboards, alerts and test reports.
- Application server timer: excludes load balancer queueing, TLS and network. Lowest numbers, easiest to collect, can miss problems in front of the app.
- Load balancer or ingress logs: includes queueing at the proxy and time to first byte from the app. A good default for API SLIs.
- Load generator (client side): includes the network path from the generator's region. This is what a load test reports, so expect it to read higher than server-side SLIs, and compare like with like.
- Real user monitoring: includes the user's network and device. Closest to experience, noisiest, and not reproducible in a test.
Worked example: an API with server-side p99 of 280 ms, measured from a load generator 40 ms away with TLS connection reuse, typically reports p99 around 320 to 340 ms. If the SLO is "p99 ≤ 400 ms at the load balancer" and the test reports client-side numbers, either subtract the known network round trip or set the test gate on the client-side number with that offset documented. Mixing them silently is how a passing test turns into a missed SLO, or a failing test into an argument.
Common mistakes
- Setting the SLO equal to the SLA. No warning margin; every internal miss is a contract breach.
- Using averages as SLIs. "Average latency < 200 ms" can be met while 5% of users wait 3 seconds. Use a threshold-based ratio or a percentile.
- Aiming for 100%. It leaves no budget for deploys or experiments, and users cannot tell 99.99% from 100% when their own network is less reliable than that.
- Load testing against the SLA. If a test only proves you can meet the contractual minimum at peak, production will regularly miss the SLO.
- Too many SLOs. Three to five per service, tied to what users notice, are easier to act on than twenty.
From SLO to load test: checklist
- Write each SLI as good events / total events, with the measurement point.
- Set SLOs above any SLA, with a window (28 or 30 days).
- Compute the error budget in minutes and requests.
- Derive load test thresholds per critical endpoint: tighter percentiles, lower error rate.
- Use identical error definitions in the test and in production metrics.
- Run long enough for the percentile you gate on, and decide how much error budget a production test may spend.
FAQ
Which is stricter, the SLA or the SLO?
The SLO should be stricter. The SLA is the contractual minimum with penalties, so the internal objective sits above it to give a warning margin. For example, an SLO of 99.9% availability supporting an SLA of 99.5%.
Is p99 latency an SLI or an SLO?
The p99 latency measurement is an SLI. A target such as p99 at or below 400 ms over 28 days is an SLO. Many teams write the same thing as 99% of requests completing in under 400 ms, which makes it easy to compute an error budget.
Do internal services need SLAs?
Usually not. Internal services benefit from SLOs that their callers can design around, but a contract with credits rarely makes sense between teams. SLAs are mainly for paying customers.
Should load test thresholds equal the SLO?
No, make them stricter. A load test is a short, controlled run, while production adds deploys, dependency failures and traffic you did not model. Leaving 15 to 25% latency headroom and a lower error rate threshold keeps a passing test meaningful.
What window should an SLO use?
A rolling 28 or 30 days is common. A 28-day window always contains the same number of each weekday, which makes comparisons cleaner. Shorter windows react faster but make the budget noisy.