SLO для live odds: freshness, availability и error budget
Для live odds SLO должен описывать пользовательское состояние: возраст версии, доступность корректного market state и управляемое поведение при деградации.

Для live odds «API отвечает быстро» не равно «пользователь видит актуальное состояние». Хороший SLO начинается с продуктового результата: возраст опубликованной версии, способность получить корректный market state и предсказуемое поведение системы во время деградации.
Разделить latency и freshness
Ответ может прийти за 40 мс и содержать состояние двухминутной давности. Поэтому request latency — отдельная метрика, а freshness измеряет расстояние между authoritative event/state time и тем, что реально опубликовано клиенту. Где брать исходную временную метку, зависит от feed contract и внутренней модели версий.
Если source timestamp ненадёжен, лучше явно выбрать другую опорную точку и задокументировать ограничение, чем строить псевдоточную метрику.
Availability должна учитывать корректный state
Endpoint, который возвращает stale или внутренне противоречивый market, формально доступен, но может быть непригоден для пользовательского сценария. Поэтому SLI можно строить вокруг доли запросов/периодов, когда клиент получает состояние, удовлетворяющее набору инвариантов: версия известна, данные не старше допустимой границы, status соответствует правилам публикации.
Suspend — не всегда ошибка
Suspend может быть правильной защитной реакцией на сомнительные данные. Считать каждую секунду suspend downtime некорректно. Полезнее различать expected suspend, защитный suspend из-за data-quality/freshness и необъяснённый suspend. Тогда SLO не наказывает систему за безопасное поведение, но показывает, когда защитный режим стал слишком частым.
Error budget превращает SLO в решение
Сам процент без правил реакции мало что меняет. Error budget нужен, чтобы заранее договориться: при каком расходе команда останавливает рискованные релизы, усиливает наблюдение или приоритизирует reliability work. Числа должны следовать из реальных требований и измерений; универсального «правильного p99» для всех операторов нет.
Считать по сегментам, а не только глобально
Глобальная метрика может скрыть деградацию одного provider, sport, competition или geography. Минимум стоит проверить, не «усредняет» ли общий показатель маленький, но критичный сегмент. При этом слишком много SLO дробит внимание, поэтому сегментацию выбирают по failure modes и impact.
Пример диагностической связки
- product SLI: доля client views со state age в целевой границе;
- pipeline signal: ingest/processing lag по provider;
- trading signal: доля защитных suspend по причине freshness;
- delivery signal: возраст последней версии на API/client edge;
- incident context: trace/version identifiers для конкретного нарушения.
Такая связка позволяет перейти от алерта «SLO горит» к проверяемой гипотезе. Если product freshness нарушена, а ingest lag нормальный, поиск смещается в processing/delivery/client path. Если lag растёт у конкретного provider, причина находится выше по цепочке.
Изменение определения SLI тоже является изменением системы измерения
Когда команда меняет источник timestamp, исключения или способ агрегации, график до и после перестаёт быть напрямую сопоставимым. Версию определения стоит хранить рядом с dashboard и incident notes. Это защищает от ситуации, когда «улучшение SLO» произошло только потому, что метрику стали считать иначе.
Burn rate полезнее одного месячного процента
Месячный SLO может выглядеть здоровым, пока error budget сгорает за один match-day. Для оперативного реагирования полезно смотреть скорость расходования бюджета на коротком и более длинном окне: это отличает краткий шум от устойчивой деградации. Конкретные окна и пороги выбираются по характеру трафика и стоимости ложного алерта. Смысл не в копировании готовой формулы, а в раннем сигнале, что текущий темп ошибок несовместим с оставшимся бюджетом.
Для отчёта полезно хранить не только нарушение SLO, но и его причину: provider gap, processing backlog, delivery error, client freshness или контролируемый suspend. Такая декомпозиция не меняет сам SLO, но позволяет понимать, какой тип отказа расходует бюджет чаще всего.
При пересмотре SLO полезно сохранять старую версию определения и дату перехода. Иначе сезонные сравнения смешивают разные правила измерения и создают ложное впечатление улучшения или ухудшения надёжности.
Так SLO остаётся инструментом эксплуатации, а не декоративным KPI.
Его определение должно быть понятно дежурной смене и владельцу продукта без дополнительной расшифровки.
SLO стоит разбирать вместе с теми, кто принимает решение о деградации
Если показатель понятен только автору dashboard, он плохо работает в инциденте. Product owner должен видеть, какой пользовательский результат нарушен, а дежурная смена — по каким техническим сигналам искать причину. Полезный companion для такого разбора — структура postmortem stale odds: она заставляет связать impact, timeline и corrective actions с теми же freshness/version сигналами, на которых построен SLO.
При сезонном трафике полезно отдельно смотреть периоды высокой нагрузки. Месячный процент может быть хорошим, если большая часть времени приходится на спокойные часы, а нарушения концентрируются на главных матчах. Это не обязательно означает необходимость отдельного SLO для каждого турнира, но отчёт должен позволять увидеть, когда именно сгорает бюджет. Иначе показатель формально выполняется, а самые важные пользовательские окна остаются системно хуже среднего.