Без чисел разговор о надёжности — это спор по вибрации. «Сделайте, чтоб не падало» — это пожелание, не задача. SLI/SLO переводят надёжность в измеряемый product trade-off: сколько багов, latency и downtime мы позволяем себе в обмен на скорость доставки фич. Без этого каждый release sparks debate «достаточно ли это надёжно», а команда живёт в режиме «всё важно — значит ничего не важно». Error budget делает явным: если SLO = 99.9%, у вас 43 минуты downtime в месяц на эксперименты, рискованные deploys и накопление technical debt. Сожгли — фризим фичи и чиним. Не сожгли — катим больше.
Mental model
SLI — что мы меряем у клиента. SLO — к чему стремимся внутри. SLA — что обещали юридически. Иерархия: SLA ⊆ SLO ⊆ SLI. SLO всегда строже SLA минимум на одну девятку — это буфер на починку до финансовой ответственности.
Три определения, которые путают чаще всего:
SLI (Service Level Indicator) — измеряемая метрика клиентского опыта: доля успешных запросов, p99 latency, freshness данных. Ключевое слово — клиентского: HTTP 200, который вернулся за 30 секунд, для пользователя фейл, даже если backend «жив».
SLO (Service Level Objective) — внутренняя цель по SLI с конкретным числом и окном: «99.9% запросов checkout завершаются за <500ms p99 за rolling 28 дней». Окно обязательно — без него «99.9%» бессмысленно (за минуту? за год?).
SLA (Service Level Agreement) — контрактное обязательство перед клиентом, обычно с финансовой пенальти. AWS S3 SLA: 99.9% uptime, иначе 10% credit; меньше 99% — 25%. Заметь: SLA сильно слабее реального uptime S3 (~99.99%) — это юридически безопасный буфер.
Error budget = 1 - SLO, выраженный в минутах или запросах за окно. Это бюджет ошибок, который команда имеет право потратить. Burn rate = во сколько раз быстрее нормы тратится бюджет. Burn = 1 — идём ровно по графику; burn = 14 — сожжём всё за 5 часов вместо месяца.
Что на диаграмме
Edge группа — где SLI меряется, потому что это граница клиентского опыта: LB, Checkout API, Auth. ADR-001 на Checkout API объясняет почему держим per-CUJ SLO вместо одного aggregate «99.9% всех 200 OK». ADR-002 — почему alerting multi-window multi-burn-rate, а не наивный «budget==0 → page».
Backend группа — зависимости (Orders, Payment, Postgres), чей SLO композируется в верхний CUJ-SLO checkout. Если Postgres даёт 99.9%, а Payment 99.95%, твой checkout-SLO физически не может быть выше произведения.
Observability группа — Prometheus скрейпит /metrics, Alertmanager роутит fast burn в PagerDuty (page), slow burn в Slack (ticket). Grafana показывает burn rate dashboard.
Decisions блок на checkout-api раскрывает ADR-001 (CUJ-based SLO) и ADR-002 (multi-window multi-burn alerting) — это два главных решения, которые надо принять при внедрении SLO.
Сценарии
Показывает, что значит «good event» для CUJ checkout: не просто HTTP 200, а 200 AND latency<500ms AND idempotency-key honored. Запрос идёт client → lb → auth → checkout-api → orders → payment → db и обратно. SLI считается per-event на edge: успех ровно тогда, когда все три условия выполнены. Если бы условие было только «HTTP 200», прозевали бы slow loris — серверы «живы», но клиент ждёт 30 секунд и закрывает вкладку.
Bad deploy → 30% ошибок на checkout-api. За 1 час сожгли >2% месячного бюджета (burn rate 14.4× normal). Multi-window правило: alert требует подтверждения и в 1h-окне (устойчивость к флапам), и в 5m-окне (точность реакции). Prometheus → Alertmanager → PagerDuty → on-call просыпается в 03
. Mitigation: rollback. Без multi-window single 5m alert флапал бы на каждом всплеске 502 от рестарта pod.
К 20-му числу месяца error budget = 0. Policy: feature freeze. Deploys ограничены reliability fixes и security patches, all-hands переключается на reliability work. Это механизм самоуправления — нет менеджера, спорящего с командой про темп. Если SLO выбран адекватно, freeze случается редко; если случается часто — либо SLO нереалистичен (слишком амбициозен), либо реально есть reliability debt, который надо платить.
Trade-offs (ADR)
ADR-001: per-CUJ SLO вместо aggregate. Один aggregate SLO «99.9% всех HTTP 200» прост и дёшев, но скрывает критичные пути. Если /healthz даёт 90% трафика и работает идеально, aggregate всегда зелёный — даже когда checkout сломан. Решение: SLO per Critical User Journey (checkout, login, search), каждый с owner-командой и квартальным review. Aggregate API SLO — secondary дашборд, не paging metric. Page on-call по user-visible симптомам (CUJ-SLO), не по причинам (CPU, queue depth).
ADR-002: multi-window multi-burn-rate alerting. Наивный alert «budget == 0 → page» приходит после катастрофы. Single short window (5m>14×) флапает на bad pod. Single long window (24h) проспит 30-минутный incident до утра. SRE Workbook предлагает два окна на severity: fast (1h AND 5m > 14.4×) → page; slow (6h AND 30m > 6×) → ticket. Threshold подбираются так, чтобы на trigger сжигалось ~2% бюджета — единая «valuта» alert noise.
ADR-003: SLO выбирается бизнесом, не SRE. Каждая девятка ~10× дороже предыдущей. 99.9% можно сделать одним регионом + грамотными deploys. 99.99% требует multi-AZ + automated failover + chaos testing. 99.999% — multi-region active-active + formal verification + dedicated reliability team. Если бизнесу хватает 3N (типичный B2B SaaS), выбор 5N сожжёт engineering velocity без видимой пользы — пользователь не отличает 99.99% от 100% в перцепции.
Реальные системы
Google SRE — родина понятий. SRE Book Ch.4 и Workbook Ch.2-5 — mandatory reading. Google Search target 99.999% global; SLI считается per-query, не per-region. Один датацентр может «исчезнуть» полностью — anycast роутит вокруг.
AWS S3 — публичный SLA 99.9% (10% credit), внутренний SLO ~99.99%. Buffer на одну девятку — стандартная практика. Feb 28, 2017: опечатка в debug-команде убрала индекс-сервис US-EAST-1 на 4 часа = 8× месячного бюджета 99.9% за один инцидент. Post-mortem привёл к change-management на capacity-modifying команды.
Stripe API — публичный SLA 99.99%, внутренний SLO 99.995% (буфер для всплесков). Error budget ~21 минута/месяц. Webhook delivery — отдельный SLO с другим окном.
GitHub Actions (2020-2023) — многократно нарушали внутренний SLO на queue time из-за runner shortages. Public status page показывает историю — пример, что 4N трудно держать на shared compute с переменным спросом.
Cloudflare — SLO per продукт (Workers, R2, KV отдельно). Транспарентные post-mortems с указанием budget consumption на каждый incident.
Anti-patterns
SLO = 100% — невозможно и убивает velocity. Карго-культ «надёжность важнее всего». Пользователь не отличает 99.99% от 100%, но команда сжигает 10× ресурсов на разницу. Если хочется 100% — это сигнал, что не понимаете цену.
SLI на инфраструктуру вместо UX — «CPU < 80%» это не SLI, это resource alert. Пользователю всё равно сколько CPU; ему важно, успешен ли его checkout. CPU метрики оставить для capacity planning, не для SLO.
Среднее latency как SLI — оно прячет хвосты. p99=2s при mean=200ms значит каждый сотый юзер ждёт 10× дольше нормы. Amazon показал: +100ms latency = -1% sales. Меряй percentiles (p95/p99/p99.9).
SLO без owner — метрика есть, дашборд горит красным, но никто не отвечает. Должен быть team owner и квартальный review «реалистичен ли target».
Слишком много SLO — 50 SLO на сервис = никто не следит ни за чем. Начни с 2-3 (availability + latency на 1-2 главных CUJ). Расширяй только когда базовые держатся стабильно.
«Synthetic SLO» из uptime checker — пинг с одной точки не отражает реальный путь пользователя через ваш CDN/DNS/edge. Реальные SLI считаются на edge из реального трафика.
Календарное окно вместо rolling — окно «May 1-31» манипулируемо концом месяца («подождём 3 дня, обновится числитель»). Используй rolling 28d — оно всегда «сейчас» и нельзя «дождаться сброса».
Page на slow burn — slow burn по определению значит «есть время до рабочих часов». Поднимать on-call ночью на 6-дневный horizon — выгорание команды без выигрыша по MTTR.
Когда НЕ использовать
Очень молодой продукт без product-market fit — у тебя пока нет стабильных CUJ. Меряй базовый uptime и latency, формальный SLO внедряй когда продукт стабилизируется и появится понятие «нормально работает».
Internal tooling, которым пользуются 10 человек — overhead на SLO process (alerts, reviews, owners) превысит пользу. Хватит «если упало — починим».
Batch / async системы без user-facing latency — SLI типа «availability» теряет смысл; ставь SLO на freshness/coverage/correctness, или вообще на business-метрики (jobs per day).
Hard real-time / safety-critical (avionics, medical) — там не SLO, а формальная верификация и certification. SLO — статистика; safety-critical требует гарантий, а не «99.999% по большой выборке».
Системы с фундаментально нестабильным dependency — если зависишь от внешнего API без SLA и без fallback, твой SLO бессмысленный. Сначала декоррелируй риск (кеш, retry, fallback), потом ставь SLO.