SLI vs SLO vs SLA: Error Budget Math with Real Uptime Data
SLI vs SLO vs SLA in one sentence: an SLI is the number you actually measure (say, "share of successful requests"), an SLO is the target you set for yourself (say, "success rate of at least 99.9% over 30 days"), and an SLA is a commitment written into a contract, with consequences if you miss it. Measurement, target, promise. The SLA is usually looser than the SLO, and the SLO sits on top of an SLI with a clearly defined scope.
Below, we take a public set of hourly request counts and work through SLI definitions, measurement windows, and error budgets. On the same 48 hours of data, weighting by request and averaging by hour differ by nearly 9 percentage points.
What are SLIs, SLOs, and SLAs?
| What it is | Who sets it | Example | What happens if you miss it | |
|---|---|---|---|---|
| SLI (service level indicator) | A measurable ratio or number | Engineering | Successful requests / valid requests | Nothing. It's just a number |
| SLO (service level objective) | The target an SLI must hit over a window | Engineering and product together | Rolling 30-day success rate ≥ 99.5% | Internal action: freeze releases, prioritize stability |
| SLA (service level agreement) | A written commitment to customers | Business and legal | Monthly uptime below X triggers agreed compensation | Contractual consequences |
A few things people mix up:
- An SLI needs a numerator, a denominator, and filter conditions. "99% availability" is not an SLI. "Over the past 30 days, requests with a non-5xx status code / all requests" is.
- An SLO always has a window. A target without a window can't be judged as met or missed.
- Not every service has an SLA. Many publish only a status page and historical uptime, with no contractual promise. For how to read those pages, see How to read the OpenAI and Claude status pages.
Where does the demo data come from?
AGI Plan publishes hourly success and failure counts per capability group at https://agiplan.dev/api/status/requests?month=YYYY-MM. No login is needed. It returns CSV by default, or JSON with format=json. AGI Plan is a commercial partner of cdnping. Here we treat it purely as a sample dataset with a public definition, and nothing in this article concerns AGI Plan's terms of service. cdnping's /en/status/agiplan page mirrors this data.
Its definition is spelled out clearly:
Availability = successes / (successes + failures caused by the platform itself). Only 5xx counts as a platform failure.
In other words, 4xx responses (including 401 auth failures and 429 rate limits) are excluded from the denominator. That choice is one of the most debated points in SLI design, and we come back to it below.
All numbers below come from a snapshot cdnping took of this endpoint on 2026-10-17 at 18:05 (Beijing time, UTC+8). cdnping only began collecting on 2026-10-17, so this is a single point-in-time sample, not a long-term statistic.
How much does the window change availability?
In the snapshot, each capability group has availability for 1-day, 7-day, and 30-day windows:
| Capability group | 1 day | 7 days | 30 days | Requests (30 days) |
|---|---|---|---|---|
| fast (fast and lightweight) | 77.35% | 81.76% | 81.73% | 44,729 |
| frontier (frontier reasoning) | 99.76% | 94.22% | 94.41% | 33,729 |
| domestic (flagship models from Chinese providers) | 98.00% | 98.23% | 98.01% | 9,436 |
| balanced (general-purpose) | 100% | 94.77% | 94.98% | 3,625 |
A few observations:
- Short windows swing a lot. The balanced group is at 100% over 1 day and 94.98% over 30 days. If you only looked at "today," you'd reach a completely different conclusion. The frontier group does the same: 99.76% over 1 day, only 94.22% over 7 days.
- Long windows dilute recent problems. The fast group's 1-day figure of 77.35% is more than 4 points below its 30-day figure, but the 30-day number looks "okay" and hides what's happening right now.
- Low-volume groups are more sensitive. The balanced group had only 3,625 requests in 30 days, so a few dozen failures visibly move the percentage.
This is why SLOs usually use a rolling 28-day or 30-day window to decide whether you're compliant, and short windows such as 1 hour or 6 hours for alerting. The two windows answer different questions.
How much can the definition change the same data?
The snapshot also contains 48 hourly buckets (from around 19:00 on October 15 to around 18:00 on October 17, Beijing time), with success and failure counts summed across groups. Over those 48 hours there were 13,963 successes and 2,177 failures. Here are three common ways to compute it:
| Method | How it's computed | Result |
|---|---|---|
| Request-weighted | Total successes / total requests | 86.51% |
| Hourly average | Compute a ratio per hour, then average | 95.17% |
| "Good hours" | Hours with success rate ≥ 99% / total hours | 26 / 48 = 54.2% |
Most of the gap comes from two hours on October 16, 14:00 to 16:00: 2,718 requests, 1,599 failures, with per-hour success rates of 47.91% and 34.16%. These were daytime peak hours with lots of traffic, so they carry heavy weight in the request-weighted figure. The hourly average treats them the same as overnight hours with only 2 requests, which pulls the result up.
Excluding those two hours, the remaining 46 hours come out at 95.69% request-weighted. Also, the first 24 hours are 83.42% and the last 24 hours are 94.95%, so even cutting the same 48-hour window in half tells two different stories.
Which method to pick depends on the question you want to answer:
- Request-weighted: reflects the probability that a user actually hits a failure. Most API services should use this.
- Time-based (good minutes or good hours): suited to very low traffic, or when you care more about "is the service usable" than "how many requests failed."
- Hourly average: best avoided. It lets quiet hours "dilute" problems that happened at peak.
Should 4xx and 429 count as failures?
This dataset has no 4xx counts, so we can't compute "availability if 429s are counted as failures." Here is just how to decide:
| Status | Common cause | Recommendation |
|---|---|---|
| 5xx | Server or upstream failure | Count as failure |
| Timeout, connection reset | Network or server | Count as failure, but separate out problems on your own network |
| 429 rate limit | Quota exceeded, or the platform shedding load when overloaded | Depends on the cause: don't count user-caused overage; do count overload-triggered limiting |
| 401/403 | Wrong key, insufficient permissions | Generally don't count |
| 400 | Malformed request | Don't count |
What matters is writing the definition down and confirming it's the same when you compare two services. If one counts 429 as a failure and the other doesn't, comparing the percentages directly is meaningless. For definition issues when running your own probes, see Measuring AI API uptime yourself. For how the same model differs across inference providers, see Same model, different OpenRouter provider: how much does uptime vary?
How much downtime does each "nine" allow?
Time-based, with 30 days taken as 43,200 minutes:
| Availability | Per week | Per 30 days | Per year (365 days) |
|---|---|---|---|
| 99% | 100.8 minutes | 7.2 hours | 87.6 hours |
| 99.5% | 50.4 minutes | 3.6 hours | 43.8 hours |
| 99.9% | 10.08 minutes | 43.2 minutes | 8.76 hours |
| 99.95% | 5.04 minutes | 21.6 minutes | 4.38 hours |
| 99.99% | 1.01 minutes | 4.32 minutes | 52.6 minutes |
| 99.999% | 6.05 seconds | 25.9 seconds | 5.26 minutes |
If your SLI is request-based, swap "minutes" for "requests": allowed failures = total requests in the window × (1 − SLO).
How do you calculate an error budget?
The error budget is the portion of failures your SLO allows. Take the frontier group, with 33,729 requests over 30 days:
- Suppose the SLO is 99%. The budget is 33,729 × 1% ≈ 337 failed requests.
- Working back from the 30-day availability of 94.41%, actual failures are about 1,887, roughly 5.6 times the budget.
- Suppose the SLO is 95%. The budget is about 1,686, and actual failures still run slightly over.
Now the domestic group: 9,436 requests, 98.01% availability over 30 days, which works back to about 188 failures. Against a 98% target the budget is about 189, right on the line. Against a 99% target the budget is about 94, and you've already spent double.
Same data, different target, completely different conclusion. That's why you shouldn't pick "99.9%" off the top of your head. Look at the SLI you've actually been delivering over some period, then decide.
Another common concept is burn rate: actual failure ratio ÷ budget ratio. With a 99% SLO and a 10% failure rate in some hour, the burn rate is 10, meaning that at this pace the 30-day budget would be gone in 3 days. The hour starting 14:00 on October 16 had a failure rate of about 52%, a burn rate of about 52 against a 99% SLO, which burned roughly 7% of the 30-day budget in a single hour. Alerts are usually set on burn rate rather than on a fixed percentage.
Hands-on: compute it yourself from the public endpoint
- Download the current month's data and look at the header and fields:
curl -s 'https://agiplan.dev/api/status/requests?month=2026-10' -o req.csv
head -3 req.csv
- Confirm which columns hold time, capability group, successes, and failures. The commands below assume successes are in column 3, failures in column 4, and there is one header row. Adjust the column numbers to match the actual header:
# Request-weighted overall availability
awk -F, 'NR>1 {ok+=$3; f+=$4} END {printf "ok=%d failed=%d sli=%.4f\n", ok, f, ok/(ok+f)}' req.csv
# Share of "good hours" with success rate >= 99% (per row; each row is one hour x capability group)
awk -F, 'NR>1 && ($3+$4)>0 {n++; if ($3/($3+$4) >= 0.99) g++} END {printf "good=%d/%d\n", g, n}' req.csv
- Compare the two results, then try dropping one capability group or looking only at business hours, and watch how the numbers move.
You can follow the same process for your own service: export hourly success and failure counts first, then compute.
How should a small team set a first SLO for an AI app?
A checklist you can follow:
- Pick one SLI that users can feel. For AI apps the most common is "share of requests to the upstream model that are non-5xx and didn't time out." Latency can be a separate SLI, for example "share of requests with time to first token under N seconds."
- Write down the filter conditions. Whether 4xx counts, how to tell 429s apart, and whether client-side cancellations count all go in the doc.
- Measure for two to four weeks before setting the target. Start from the SLI level you actually achieve and set the target slightly above current performance, rather than writing 99.9% first and finding out you can never hit it.
- Account for upstream. If the model API you depend on only reaches a certain level, your SLO can hardly be higher than that unless you add retries or multi-provider failover. You can check upstream status on API status and Is it down?, and see past incidents in AI service incident roundup: September-October 2026.
- Set two tiers of burn-rate alerts, each with one long and one short window, firing only when both windows exceed the threshold to cut false alarms. For a 99.9% SLO over 30 days, the Google SRE Workbook gives a reference set: notify immediately when the burn rate exceeds 14.4 over both a 1-hour and a 5-minute window, and also notify when it exceeds 6 over both a 6-hour and a 30-minute window. Adjust the values to your own SLO and traffic.
- Agree on what happens when the budget is spent. For example, pause non-urgent releases and prioritize stability work. An SLO with no action attached is just a number on a dashboard.
For concrete probe scripts and alert configuration, continue with How to monitor AI app availability. cdnping's own probing approach and definitions are described on the methodology page.
What should you ask when reading someone else's uptime number?
- What are the numerator and denominator, and how are 4xx, 429, and timeouts treated?
- Is the window 1 day, 7 days, or 30 days, and is it a calendar month or rolling?
- Is it request-weighted or time-based?
- Is it real requests counted server-side, or an external probe? External probes are samples at a fixed interval (for example, cdnping's API status probes every 5 minutes) and can't be compared directly with real-request results.
- Can you get the raw counts and recompute it yourself?
When evaluating third-party API services, these questions pair well with How to choose an AI API relay: 8 checks.