Other ways to count an SLO

The first page counted time: chop the month into windows, count the bad ones. That is one choice among several. This page walks through the others — counting requests instead of minutes, rolling instead of calendar periods, and percentiles instead of thresholds — using the same month, the same incidents, and the same diurnal traffic curve, so the bills can be compared directly.

1Request-based: count events, not minutes

A request-based SLI is good requests ÷ all requests over the whole period. There are no windows and no per-window verdicts: every failed request spends one unit of budget, and the budget is a number of requests: (1 − SLO) × everything you served that month. Traffic now matters. Below, the same 30-minute full outage happens once at 03:00 and once at 15:00.

no failures (darker = less traffic) failed requests (brighter = more)

2The same month, billed two ways

Here is one month with three very different incidents: a short full outage at peak, a long partial degradation overnight, and a day of "everything works, just 0.5% worse". Each is billed by the window method and by the request method side by side. Edit them; the two columns rarely agree on which one was expensive.

Window-based

Request-based

3Calendar month or rolling 30 days?

Whichever way you count, you count over a period. A calendar period resets on the 1st: the SLI starts fresh, and yesterday's outage is forgotten. A rolling period is always "the last 30 days": an outage keeps counting until it ages out, then drops off a cliff. Drag one 45-minute outage across three months and watch how long each method holds it against you.

calendar month to date rolling 30 days SLO target (dashed)
Calendar: days out of compliance
Rolling: days out of compliance

4Latency: a percentile per window, or a fraction of requests?

"p95 latency under 300 ms" can be counted two ways. Per window: compute each window's p95, and the window is bad if it's over 300 ms — a window-based SLO with a percentile as its threshold. Per request: each request under 300 ms is good, and the SLO is "95% of requests are good" — a request-based SLO. Below is one day with a nightly batch job that makes a share of the 03:00 traffic slow.

requests per minute per-window p95 (ms, right axis) windows whose p95 > 300 ms
Per window: windows with p95 ≤ 300 ms
Per request: requests ≤ 300 ms
The trap: average of the per-window p95s

5Choosing

None of these is the right one. They answer different questions, and the honest choice is the one that matches the promise you actually made.

What is countedBudget unitSees traffic?Sees severity?Good for
Window-basedwindows whose SLI cleared a thresholdminutesnono: a window is bad or it isn'tuptime-style promises, paging, services with steady traffic, anything you'd say "was down for 40 minutes" about
Request-basedrequests that succeededrequestsyesyes: 50% down costs half of 100% downuser-experienced reliability, bursty or diurnal traffic, chronic low-level degradation
Calendar periodeither, from the 1steithervolatile early in the period, forgiving late; lines up with reports and contractsSLAs, monthly reviews
Rolling periodeither, over the trailing N dayseitherevery incident counts for exactly N days; no reset-day amnesiaalerting, error-budget policies, "are we healthy right now"
Percentile per windowwindows whose p95/p99 cleared a barminutesnonolatency promises where a bad minute matters regardless of who saw it; never average the percentiles afterwards
Whatever you pick, pick it out loud. "99.9%" means nothing until you say 99.9% of what, judged how, over which period. Two teams can both be right about the same month and disagree about whether the SLO was met.