Most first-draft SLOs die in a spreadsheet nobody opens again. Here is the target-setting process that survived contact with three different teams.

Our first SLOs were guesses dressed up as math: 99.9% because it sounded serious, 30-day windows because a blog post said so. Nobody believed them, and nobody paged off them for a year.

Start from what users actually noticed

We stopped opening with a target and started opening with an incident log. For each of the last six months, we asked: was there a period where users would have filed a complaint, even an informal one in Slack? We counted those windows in minutes, not vibes.

That gave us a real baseline: our checkout API had roughly 41 minutes of user-visible badness a month. Not zero. Not the four-and-a-half-minutes-a-month that 99.99% implies. We set the SLO at 99.9%, which allows about 43 minutes — close enough to current reality that the team could hit it without heroics, and tight enough to force fixing the worst offender.

Make the SLI boring and specific

Vague SLIs ("the API is fast and reliable") produce vague arguments during incidents. We defined ours as a single HelixQL query anyone could run and get the same number.

from traces
| where service == "checkout-api" and span.kind == "server"
| extend good = duration < 300ms and status_code < 500
| summarize good_ratio = avg(good) by bin(_time, 5m)

Get sign-off from the people who get paged

The SLO went to the on-call rotation before it went to leadership. If the engineers carrying the pager think a target is unreasonable, it will quietly rot the first time it's inconvenient. We ran a 30-minute review where the rotation could veto the number — two of five services had their targets loosened after this step, and adoption jumped because of it, not despite it.

Publish the reasoning, not just the number

Every SLO doc now carries a short "why this number" section alongside the target itself — the incident baseline it was derived from, the date it was last reviewed, who signed off. Six months later, when someone questions why the target is 99.9% and not 99.95%, the answer already exists in the document instead of requiring someone to reconstruct the reasoning from memory or re-run the original analysis from scratch.

  • Derive the target from a real incident baseline, not an industry benchmark.
  • Write the SLI as one HelixQL query the whole team can run and trust.
  • Get the on-call rotation to sign off before publishing the number.
  • Publish the reasoning behind the target next to the target itself.
  • Revisit the target after the first quarter — don't treat it as permanent.