Цена даунтайма и работа со временем восстановления: метрики MTTR/MTBF, организация инцидентного потока, ChatOps и публичные статус-страницы
Даунтайм — это не только потерянная выручка за часы простоя. Это разорванные SLA, штрафы, отток клиентов и медленная эрозия доверия, которую невозможно посчитать в моменте. Эта статья — про то, как измерять время восстановления честно, почему интуиция врёт про "у нас всё стабильно", откуда берётся длинный MTTR в средних компаниях и как организовать инцидентный поток так, чтобы реагировать на…

В разговорах с владельцами бизнеса часто звучит фраза, которая выдаёт всё сразу: "у нас всё стабильно работает, проблем нет". Это самообман в чистом виде. Не потому, что обязательно есть скрытые проблемы — а потому, что никто не считает. Если в компании нет централизованного учёта инцидентов, то любой даунтайм короче пятнадцати минут просто исчезает из коллективной памяти на следующий день. Сайт лежал две минуты в пятницу вечером — сисадмин рестартанул сервис, никому не сказал, инцидент не зафиксирован. Через неделю клиент пишет в поддержку: "у вас вчера ничего не работало, я не смог оформить заказ". Поддержка отвечает: "у нас всё стабильно работает". И обе стороны искренне правы — каждая со своей точки наблюдения.
Реальная картина видна только тогда, когда есть единая таблица инцидентов с временными метками: когда обнаружили, когда подтвердили, когда исправили. Тогда становится возможным считать четыре ключевые метрики надёжности, и каждая из них говорит о своей части проблемы.
MTTR — Mean Time To Recovery, среднее время восстановления — самая обсуждаемая метрика, но и самая лукавая. Это время от момента, когда инцидент создан, до момента, когда сервис снова работает. Звучит просто, но в эту метрику легко спрятать всё что угодно. Например, если инцидент создаётся только после того, как кто-то заметил проблему через час после её начала, MTTR будет красивым, а реальный даунтайм — нет. Поэтому MTTR имеет смысл только в паре с MTTD.
MTTD — Mean Time To Detect, среднее время обнаружения — время от реального начала проблемы до её фиксации в системе. Это самая болезненная метрика для большинства компаний, потому что в наивной настройке мониторинга MTTD равен бесконечности — проблема обнаруживается только когда позвонил клиент. Хороший мониторинг сокращает MTTD до секунд: метрика вышла за порог, алерт прилетел, инцидент создан автоматически. Плохой мониторинг — это когда есть Zabbix с тысячью метрик, никто на них не смотрит, алерты идут на почту, которую никто не читает, потому что там сто алертов в день и среди них пять реальных.
MTTA — Mean Time To Acknowledge, среднее время подтверждения — сколько проходит от создания инцидента до момента, когда живой человек сказал "вижу, занимаюсь". Эта метрика измеряет качество дежурной смены. В компании без формализованного дежурства MTTA — это часы и иногда сутки. Алерт прилетел в час ночи в воскресенье, инженер увидел в понедельник утром, инцидент уже сам по себе разрешился (или нет). В компании с грамотным on-call MTTA — это две-три минуты: алерт в Telegram, дежурный нажал /ack из чата прямо со смартфона, не открывая ноутбук.
MTBF — Mean Time Between Failures, среднее время между отказами — обратная сторона надёжности. Если MTTR показывает, как быстро чините, то MTBF показывает, как часто ломается. Высокий MTBF при высоком MTTR — это редкие, но долгие катастрофы. Низкий MTBF при низком MTTR — это постоянная мелкая дрожь, которая в сумме съедает столько же часов простоя, но раздражает клиентов сильнее, потому что воспринимается как хроническая нестабильность.

Раздел Инциденты — единая лента событий с фильтрами по severity, статусу и временному окну. Без такой ленты считать MTTR невозможно, потому что половина инцидентов остаётся в чужой памяти, а не в системе
Цена даунтайма редко рассчитывается честно. Самая популярная модель — "выручка за час, делённая на 24 часа, умноженная на часы простоя". Эта формула годится только для интернет-магазина, который работает 24/7, и то с натяжкой. Реальная цена даунтайма складывается минимум из пяти компонентов, и часть из них вообще не выражается в деньгах напрямую, но рано или поздно появляется в P&L под другими именами.
Первый компонент — прямые потери выручки. Здесь работает простая модель: годовая выручка делится на 8760 часов в году, умножается на количество часов простоя и на коэффициент зависимости бизнеса от системы. Для классического e-commerce коэффициент близок к единице — лежит сайт, нет заказов. Для интранет-портала кадровой системы коэффициент 0.1 — работа не останавливается, просто становится менее эффективной. Для биржевой платформы коэффициент может быть выше единицы — за час простоя теряется не только пропорциональная часть выручки, но и сделки, которые перетекают к конкуренту и не вернутся.
Второй компонент — штрафы по SLA. Если компания продаёт B2B-сервис с гарантией 99.9% uptime в месяц, это означает допустимый даунтайм в 43 минуты в месяц. Превысили — обязаны вернуть процент абонентской платы. Тут важна не сумма возврата, которая может быть символической, а сам факт срабатывания пункта SLA: клиент получает формальное подтверждение, что сервис ненадёжен, и в следующем тендере смотрит на конкурентов.
Третий компонент — нагрузка на службу поддержки. Каждые пять минут полноценного даунтайма крупного сервиса генерируют десятки обращений в саппорт. Это перегруженные операторы, длинные очереди, раздражённые клиенты, временные сотрудники, которых нужно нанять, чтобы разгрести вал. Эти расходы редко попадают в строку "потери от инцидента", но они есть.
Четвёртый компонент — репутационный шлейф. Самый трудный для оценки, но самый дорогой в долгую. Каждый клиент, который не смог купить, — это не только потерянная сделка сегодня, но и человек, который завтра расскажет коллегам "там у них постоянные проблемы". Особенно болезненно это в B2B, где решения о покупке принимаются месяцами и где случайный негативный сигнал в нужный момент способен сорвать тендер на миллионы.
Пятый компонент — внутренние издержки реагирования. Это зарплата команды, которая занимается инцидентом вместо плановой работы. Если сеньорный инженер с почасовой ставкой в десять тысяч рублей четыре часа разбирает аварию вместо разработки фичи, к стоимости инцидента честно прибавляется сорок тысяч плюс упущенная стоимость фичи, которую он не сделал. В крупных инцидентах подключается несколько человек — счёт растёт быстро.
Если посчитать всё пять составляющих для среднего российского e-commerce с выручкой 500 миллионов в год, час даунтайма обходится примерно в 250–400 тысяч рублей. И это нижняя оценка, которая не учитывает долгосрочный репутационный шлейф. Для крупного B2B-сервиса с регулируемой отраслью цифры могут быть в десять раз выше.
Отдельная история — корректный расчёт SLA по uptime. Здесь у большинства команд творится математическая каша. Считают по часам в месяце, считают по часам в году, считают только рабочее время, считают только время, когда есть пользовательский трафик. Каждый из этих подходов даёт радикально разные цифры, и при заключении договоров с клиентами эта неопределённость регулярно превращается в споры. 99.9% в месяц — это 43 минуты допустимого даунтайма. 99.9% в год — это уже 8 часов 45 минут. Разница в десять раз. При обсуждении SLA важно сразу зафиксировать базу расчёта и метод измерения: считается ли каждая секунда недоступности, или считаются только инциденты длительностью больше N минут, считается ли запланированное обслуживание в окно даунтайма или вычитается. От ответов на эти вопросы зависит, выполнимо ли обязательство в принципе и сколько оно стоит провайдеру.
Откуда берётся длинный MTTR в средней компании
Если расписать процесс реагирования на инцидент в типичной российской компании среднего размера, получается примерно такая картина. Что-то ломается. Через двадцать-сорок минут это замечает либо клиент через поддержку, либо сотрудник через "у меня тут не работает". Поддержка идёт в чат к админам в Telegram или Mattermost, описывает проблему. Дежурный админ смотрит, какие у него есть подсказки — открывает в кабинете облачного провайдера панель сервера, смотрит метрики (не всегда понятно, где какой сервер хостится), пытается зайти по SSH. Где-то записан пароль или ключ, надо вспомнить где. Подключается, запускает top, видит что нагружен CPU. Запускает ps, ищет процесс. Принимает решение — перезапустить сервис. Перезапускает. Ждёт. Проверяет. Работает. Возвращается в чат: "поправил".
В этой истории прошло сорок минут MTTD (пока заметили) плюс ещё двадцать-сорок минут MTTR (пока чинили). Час даунтайма. На каждой стадии есть очевидные проблемы. Мониторинга нет либо он есть, но никто на него не смотрит. Инцидент существует только в виде сообщения в чате — нет ни severity, ни affected systems, ни timeline. Дежурный действует по памяти и интуиции, потому что нет playbook'а — нет документа, в котором написано "если CPU выше 90% на сервере с категорией веб-фронт, то делаем это и это". В следующий раз, когда такая же проблема случится у другого админа, он будет изобретать процесс с нуля.
Дальше начинается стадия записи. После того как починили, инцидент в идеале должен быть зафиксирован — что случилось, как починили, что нужно предотвратить. На практике этого не делается, потому что нет инструмента. Можно завести задачу в Jira, но Jira про другое, она про спринты. Можно написать в Confluence — но никто не читает. Чаще всего инцидент растворяется в общем потоке чата, и через неделю никто не помнит подробностей.
Здесь имеет смысл задержаться на разнице между двумя понятиями, которые часто путают: мониторинг и наблюдаемость. Мониторинг — это набор заранее заданных метрик и порогов: процент использования CPU, занятое место на диске, количество ошибок 5xx, длительность ответа. Если метрика выходит за порог — алерт. Наблюдаемость (observability) — это способность по поведению системы извне восстановить, что происходит внутри, даже если конкретный сценарий не был предусмотрен заранее. Мониторинг отвечает на вопрос "работает ли система так, как ожидалось". Наблюдаемость отвечает на вопрос "почему она работает не так, как ожидалось". В контексте MTTD мониторинг сокращает время обнаружения известных проблем, наблюдаемость — неизвестных. Хорошо настроенный мониторинг ловит за минуты падение сервиса или превышение нагрузки. Только наблюдаемость даёт шанс понять, что новая версия приложения тратит на 30% больше памяти, чем предыдущая, и через неделю упрётся в лимит контейнера. COSCIO встроенно собирает оба слоя: метрики через стандартные health-чеки и счётчики, а через трейсинг и структурированные логи — данные для наблюдаемости.
Главная проблема среднего MTTR — это не плохие админы. Админы как раз обычно неплохие. Проблема в фрагментации. Мониторинг отдельно (часто несколько систем — Zabbix для серверов, Sentry для приложений, UptimeRobot для внешних проверок). Алерты отдельно (часть в почту, часть в Slack, часть никуда). Управление инцидентами отдельно (нигде). Документация по реагированию отдельно (на Confluence в виде неактуальной wiki). Доступ к серверам отдельно (через прыжки и пароли в LastPass). Каждый переход между этими системами — это минуты, а в инциденте минуты — это деньги.
Подход, который реализован в COSCIO, исходит из обратного принципа: всё должно быть в одном месте, и каждое действие должно требовать минимум кликов. Раздел Incidents в COSCIO — это централизованный поток всех инцидентов компании, независимо от того, как они возникли. Алерт пришёл от мониторинга метрик — инцидент создаётся автоматически. Health-check сайта зафиксировал недоступность — инцидент. Security-сканер увидел подозрительную активность — инцидент. Админ заметил что-то сам и хочет зафиксировать — кнопка "создать инцидент" вручную.

Дашборд COSCIO — баннер CriticalAlertsBanner вверху показывает активные критические инциденты, AiInsightsPanel предлагает разбор и рекомендации. Цель — чтобы любой человек, открывший систему, за секунду понимал, что сейчас горит
Каждый инцидент в COSCIO имеет структуру, которая отвечает на главные вопросы. Severity — насколько критично: critical (полная потеря сервиса), high (деградация, большая часть пользователей затронута), medium (частичная деградация), low (косметика, не критично). Affected — что именно затронуто: список серверов и список сервисов. Timeline — автоматически собираемая хронология событий: когда создан, когда подтверждён, какие действия выполнены, когда разрешён. Notes — текстовое поле для контекста и комментариев команды. Root cause — заполняется уже после resolved, в фазе postmortem.
Состояния инцидента упрощены до минимально необходимого набора. Open — только что создан, никто ещё не подтвердил. Acknowledged — кто-то взял на себя, занимается. Resolved — проблема устранена, сервис работает. Postmortem — этап написания разбора (опционально, для критичных инцидентов). Лишних статусов нет специально: чем больше состояний в workflow, тем больше энергии тратится на их поддержание, а сама работа над инцидентом начинает уступать работе над тикетом про инцидент.
AI Incident Analysis — это функция, которая запускается автоматически при создании инцидента. AI получает контекст: что случилось (текст алерта), на каком сервере, какие метрики были перед инцидентом, какие логи отметились в этот момент, какие похожие инциденты были раньше. На выходе — короткий разбор: что вероятно произошло, какие действия имеет смысл предпринять, на что обратить внимание. Это не замена инженеру, а ускорение: когда дежурный открывает инцидент, он сразу видит контекст и гипотезы, а не пустое поле.
ChatOps как способ ускорить MTTA
Между моментом создания инцидента и моментом, когда дежурный нажал "вижу, разбираюсь", обычно проходит больше времени, чем нужно. Причина чаще всего не в том, что дежурный медленный, а в том, что путь до подтверждения слишком длинный. Алерт в почте — нужно открыть почту, найти письмо, перейти по ссылке, авторизоваться в админке, найти инцидент, нажать кнопку. Это занимает три-пять минут в лучшем случае, и это если инженер уже за компьютером. Если он в дороге или в магазине, это вообще нереально.
Telegram-бот в COSCIO решает задачу иначе. Алерт приходит в групповой чат команды. В сообщении сразу есть кнопки и команды: можно ответить /ack <incident_id>, и инцидент сразу переходит в Acknowledged с указанием, кто подтвердил. Можно ответить /resolve <id>, когда проблема решена. Всё это занимает секунды и не требует открывать ничего, кроме привычного мессенджера, который и так открыт двадцать четыре часа в сутки.
Telegram как канал для ChatOps выбран не случайно. В российской команде у всех есть Telegram — это нулевой порог входа. Slack распространён в IT, но за пределами IT-команды или в смешанных компаниях ставить ещё одно приложение для пары алертов — лишняя сущность. Mattermost — корпоративный аналог, но он редко стоит на смартфонах вне рабочего времени. Telegram — стоит у всех. Доставка мгновенная, групповые чаты с тредами поддерживают любую структуру команды (общий канал для критики, узкие для команд DevOps, базы данных, фронта), интерактивные команды через бота работают надёжно.
Notifications в COSCIO — это вообще отдельная подсистема, которую важно понимать как многоканальную. Один и тот же инцидент может в зависимости от важности и предпочтений конкретного человека прилететь сразу несколькими путями: SSE-уведомление в самом приложении (если человек сидит за компьютером и открыт COSCIO), email (как письменный след для отчётности), Telegram (для оперативной реакции), SMS (для критики ночью, если человек не реагирует на Telegram в течение N минут), VK MAX (как альтернативный мессенджер). Каждый пользователь сам настраивает, какие типы событий и какой severity приходят по каким каналам.

Уведомления — экран настройки каналов: per-user предпочтения по типам событий, чтобы не получать SMS среди ночи о low-severity инциденте, но гарантированно получить SMS о critical, если Telegram-уведомление осталось без ответа десять минут
Auto-Remediation и его границы
Самая дискуссионная функция в управлении инцидентами — автоматические действия по их разрешению. Auto-remediation выглядит магически: алерт приходит, система сама понимает, что делать, сама делает, сама проверяет, что помогло, и сама закрывает инцидент. В реальности так бывает только для очень узкого класса проблем, и за пределами этого класса автоматизация быстро превращается из помощника во врага.
Главное правило: playbook должен быть идемпотентен. Это означает, что повторный запуск не должен ломать систему. Если playbook делает "рестарт сервиса nginx", его можно безопасно вызвать дважды подряд — во второй раз ничего страшного не случится. Если playbook делает "добавить запись в crontab", его повторный запуск создаст дубликаты, что неприятно. Любой неидемпотентный playbook — это бомба замедленного действия, потому что система рано или поздно запустит его повторно (из-за глюка, гонки, ошибки в условии срабатывания).
Второе правило: playbook должен иметь верификацию. После того как playbook сделал свою работу, должна быть проверка, что цель достигнута. Если playbook рестартует сервис, после рестарта нужно проверить, что сервис действительно поднялся и отвечает на запросы. Если playbook очищает диск, после очистки нужно проверить, что свободного места стало достаточно. Без верификации система живёт в иллюзии, что починила, а на самом деле, например, рестарт упал из-за синтаксической ошибки в конфиге, и сервис лежит ещё более глубоко мёртвый, чем был.
Третье правило: всё должно логироваться в инцидент. Каждое действие playbook'а пишется в timeline инцидента с меткой времени и результатом. Это критично для postmortem: если потом кто-то будет разбираться, что произошло, он увидит не только саму проблему, но и все попытки её решить.
В COSCIO встроены пять стандартных playbook'ов, каждый из которых иллюстрирует свой класс задач и свои нюансы.
High CPU — реакция на устойчивую высокую загрузку процессора. Playbook сначала собирает информацию: ps -eo pid,pcpu,comm --sort=-pcpu | head — топ процессов по нагрузке. Если в первой строке знакомый процесс из белого списка (например, nginx-worker, который иногда заклинивает) — рестарт известного сервиса. Если процесс незнакомый — алерт человеку без автоматических действий, потому что незнакомый процесс может быть как штатной задачей бэкапа, так и майнером, и решение должен принять человек.
Disk Full — реакция на заполненный диск. Сначала анализ — du -h --max-depth=2 /var/log и /tmp, поиск файлов больше определённого размера. Дальше — ротация: сжатие старых логов, удаление файлов из /tmp старше определённого возраста, опционально — очистка системных артефактов вроде кэша apt. После — проверка, что свободного места действительно стало больше порога. Здесь критична настройка белого списка путей — playbook никогда не должен трогать пути, которые не объявлены явно безопасными для очистки.
Service Down — реакция на падение сервиса. Самый прямолинейный playbook: systemctl restart <service>, пауза 30 секунд, systemctl status <service> для проверки. Если поднялся — закрываем инцидент с пометкой "auto-resolved by restart". Если не поднялся — эскалация человеку с собранным контекстом: последние строки журнала journalctl, статус всех зависимых сервисов, недавние изменения в конфиге (если отслеживаются).
SSL Expiring — реакция на приближение истечения SSL-сертификата. Этот playbook принципиально не выполняет remediation сам, потому что вмешательство в certbot-процесс автоматизированно — это очень тонкая работа, легко сломать прод. Вместо этого playbook генерирует напоминание за 7 дней до истечения, с деталями (какой домен, какой сертификат, на каком сервере), и эскалирует ответственному. Иногда лучшая автоматизация — это надёжное напоминание человеку.
Brute Force — реакция на массовые попытки подбора паролей с одного IP. Playbook анализирует логи (auth.log для SSH, либо nginx access log для веб-форм), считает количество попыток за интервал, и при превышении порога добавляет IP в UFW deny на час (если эта функция включена в настройках правила). Параллельно — алерт о подозрительной активности с деталями. Час — компромисс: достаточно, чтобы остановить атаку, недостаточно, чтобы создать долгосрочные проблемы для случайно заблокированных легитимных пользователей.
Кроме этих пяти, в COSCIO можно создавать кастомные playbook'и для специфичных задач компании: рестарт конкретного приложения, очистка определённого кэша, перезапуск воркера очереди, отправка тестового запроса в API. Каждый кастомный playbook — это последовательность шагов (SSH-команда, API-вызов, проверка условия) с описанием expected result для верификации.
MaintenanceWindow — почему он критически важен
Auto-remediation без понятия о плановых работах превращается в кошмар. Сценарий, который случается в любой команде, не имеющей этой защиты: в субботу вечером команда деплоит обновление. Деплой требует рестарта основного приложения. Приложение во время рестарта на пятнадцать секунд не отвечает. Health-check, который дёргает приложение каждые десять секунд, фиксирует недоступность. Создаётся инцидент severity high. Срабатывает auto-remediation для service-down: systemctl restart приложение. Деплой-процесс, который как раз в этот момент сам перезапускал приложение, ломается. Состояние неконсистентно, начинаются каскадные сбои.
MaintenanceWindow — это запланированное окно обслуживания, в течение которого подавляются автоматические действия и большинство уведомлений. Перед началом любых работ ответственный инженер открывает в COSCIO раздел MaintenanceWindow, создаёт окно с указанием времени начала, длительности, затронутых серверов и сервисов, кратким описанием работ. Дальше всё внутри этого окна обрабатывается по особым правилам: алерты с указанных серверов не создают инциденты автоматически (или создают, но без уведомлений), auto-remediation не запускается, на Public Status Page показывается баннер "плановые работы, ожидаемое окончание такое-то".
Когда окно закрывается (по таймауту или вручную), система возвращается в обычный режим. Это исключительно простая идея, но без неё любая попытка автоматизировать инцидентный поток обречена на трение между автоматикой и плановыми операциями команды.
Public Status Page — публичная и внутренняя
Status Page — это страница, которая показывает текущее состояние сервисов. В COSCIO их две, и важно понимать различие. Внутренняя Status Page (/status) — для команды. Там видны полные имена серверов, IP-адреса, реальные метрики, технические детали инцидентов. Это рабочий инструмент дежурного, а не публичная коммуникация.

Внутренняя Status Page — реальные имена серверов, текущие метрики, активные инциденты. Это рабочий экран дежурного, не для клиентов
Public Status Page (/public-status) — внешняя страница, которая доступна без авторизации. Там видны не серверы, а сервисы в понятных пользователю терминах: "Сайт", "Личный кабинет", "API оплаты", "Email-уведомления". Каждый сервис имеет цветовой индикатор: зелёный (всё работает), жёлтый (частичная деградация), красный (недоступен). При активном инциденте показывается короткое сообщение для пользователей — без технических деталей, без имён серверов, в формате "наблюдаем замедление в личном кабинете, инженеры работают над устранением".
Public Status Page — это инструмент управления клиентским опытом во время инцидентов. Когда клиент видит, что сервис лежит, его первая реакция — позвонить в поддержку или написать в чат. Если на Public Status Page открыто и честно показано "знаем, чиним, ожидаемое восстановление через 20 минут", значительная часть звонков не происходит. Клиент видит, что проблема замечена, что над ней работают, что есть оценка времени. Это снижает нагрузку на поддержку в момент инцидента в разы, а главное — даёт клиенту чувство контроля. Молчание во время инцидента воспринимается как непрофессионализм; честное публичное сообщение — как зрелость.
Есть распространённая ошибка: показывать на Public Status Page всегда зелёный цвет, потому что "не хочется пугать клиентов". Это иллюзия защиты репутации. Клиенты не дураки — они видят, что что-то не работает, идут на Status Page, видят зелёное, делают вывод "врут". Дальше доверие к Status Page как источнику правды теряется навсегда, а вместе с ним — и часть доверия к компании в целом. Лучше показывать жёлтое, когда есть проблема, и иметь репутацию честной системы, чем показывать всегда зелёное и иметь репутацию системы, которой нельзя верить.
MaintenanceWindow тоже показывается на Public Status Page — за несколько часов до начала появляется баннер "плановые работы запланированы на такое-то время, ожидаемая длительность такая-то, что именно будет недоступно". Это снимает существенную часть негатива: клиенты, которые знали о работах заранее, не воспринимают их как сбой.
Postmortem — самая недооценённая практика
После того как инцидент закрыт (статус Resolved), на самом деле работа над ним только начинается. Самая ценная часть инцидентного процесса — postmortem, разбор того, что произошло, почему, и что нужно сделать, чтобы такое не повторилось. В абсолютном большинстве компаний postmortem не делается вообще или делается формально для самых громких инцидентов, после чего файл забывается на shared drive.
COSCIO предлагает простой workflow: после перехода инцидента в Resolved ответственному (тому, кто разрешил инцидент, или тому, кто назначен ответственным за систему) приходит напоминание о необходимости написать postmortem. Сам postmortem — это структурированное поле внутри инцидента с разделами: root cause (что именно сломалось на техническом уровне, не "сайт упал", а "контейнер приложения OOMKilled из-за утечки памяти в библиотеке X версии Y, которую обновили вчера"), timeline (хронология с метками времени), что было сделано (какие действия, в каком порядке, какие сработали, какие нет), что нужно сделать, чтобы предотвратить (конкретный список задач с ответственными).
Postmortem остаётся внутри инцидента и доступен всей команде. Со временем это превращается в коллективную базу знаний — когда случается похожий инцидент, можно быстро найти похожие случаи и сразу применить уже известные решения. Без postmortem каждый инцидент проживается командой как первый, опыт не накапливается, MTTR не улучшается.
Важная культурная установка: postmortem не должен искать виноватого. Хорошая практика — blameless postmortem, разбор без обвинения конкретного человека. Если выяснилось, что инженер X выкатил баг, который положил прод, ценность не в том, чтобы X наказать, а в том, чтобы понять, как процесс выкатки позволил этому случиться. Если виноват инженер — значит, виноват процесс, который не имел подстраховки от человеческой ошибки. Это сложно принять, особенно в иерархических культурах, но без этого никакая система postmortem не работает: люди начинают скрывать инциденты или формализовать разборы, лишь бы избежать неприятностей.

Бэкапы как один из частых источников инцидентов. Сбой бэкапа сам по себе не виден пользователям, но в момент когда понадобится восстановление — становится фатальным. Здесь инциденты создаются автоматически при провале бэкап-задачи
Архитектурное замечание: почему BullMQ
Вопрос "на чём строить очередь задач для playbook'ов" в любой команде неизбежно превращается в холивар. Celery в Python-стеке, Sidekiq в Ruby, n8n как low-code, Temporal как современный workflow-движок, AWS Step Functions для облака. COSCIO построен на TypeScript-стеке с Next.js и PostgreSQL, и для очередей выбран BullMQ. Это решение основано на нескольких прагматичных соображениях, которые стоит проговорить.
Во-первых, BullMQ — это TypeScript-native решение. Не нужно держать второй язык программирования и второй рантайм для воркеров. Те же типы, та же кодовая база, тот же подход к ошибкам и логированию. Это снижает когнитивную нагрузку на команду и упрощает поддержку.
Во-вторых, Redis уже есть в стеке (используется для кэша, сессий, лимитов). Добавление BullMQ не требует поднимать новую инфраструктуру — он использует уже существующий Redis как backend. Это контрастирует с Temporal, который требует отдельного кластера со своим хранилищем и операционными издержками.
В-третьих, BullMQ имеет хорошую observability. Каждое задание имеет состояние (waiting, active, completed, failed, delayed), историю попыток, прогресс выполнения. Это критично для playbook'ов: когда что-то идёт не так, нужно сразу видеть, на каком шаге упало, какая была ошибка, сколько раз retry'илось.
В-четвёртых, BullMQ поддерживает scheduled jobs и rate-limiting из коробки. Это важно для playbook'ов с cooldown'ами и для cron-задач (типа проверки SSL-сертификатов раз в день).
Целый отдельный воркер-процесс (worker-entrypoint.ts) запускается рядом с основным Next.js-приложением. Это правильное разделение: реквесты пользователей и фоновые задания не должны делить одни и те же ресурсы. Если playbook взял CPU на исполнение SSH-команды, это не должно замедлить рендер дашборда другого пользователя.
Что дальше делать с этим всем
Главный вопрос, который остаётся после описания инструментов: с чего начать. Никто не внедряет полноценную систему управления инцидентами за один день. Реалистичный путь выглядит так.
Первый шаг — начать считать. Завести таблицу инцидентов (в Excel, в Notion, в Linear, где угодно), фиксировать в неё каждый случай, когда что-то ломалось. Время начала, время фиксации, время разрешения, severity, что сломалось, что сделали. Через месяц этой простой практики появляется первая честная картина: сколько на самом деле инцидентов, какой реальный MTTR, какие системы ломаются чаще. Эта картина почти всегда удивляет — обычно неприятно.
Второй шаг — централизовать алерты. Свести все источники уведомлений в один поток. Не пять разных каналов в Slack, в которые пишет пять разных систем, а единый поток, который собирает всё в одно место и применяет правила: что считается critical, что high, что игнорировать.
Третий шаг — формализовать дежурство. Расписание дежурств с явной ответственностью: кто on-call с такого-то по такое-то, кто backup, как происходит передача смены. ChatOps — это инструмент, но без человеческой структуры он бесполезен.
Четвёртый шаг — написать первые playbook'и для самых частых инцидентов. Даже без автоматизации, просто как документ "что делать, если упал сервис X": последовательность шагов, проверки, эскалация. Половина MTTR — это время на размышление "что вообще делать", и хороший playbook убирает эту половину.
Пятый шаг — внедрить postmortem-культуру. Хотя бы для критичных инцидентов: каждый critical разбирается, разбор сохраняется, в нём есть конкретные пункты "что нужно предотвратить". Через год такой практики количество критичных инцидентов сокращается в разы — не потому, что система стала надёжнее сама по себе, а потому, что коллективное знание команды позволяет ловить проблемы на ранних стадиях.
И только когда все эти основы есть, имеет смысл думать про auto-remediation. Автоматизация — это усилитель: она усиливает хорошие процессы и усиливает плохие. Если процесс реагирования на инциденты у команды хаотичный, автоматизация сделает хаос масштабнее. Если процесс выстроен, автоматизация снимает с команды рутину и позволяет тратить время на нетривиальные случаи.
Отдельный важный нюанс — связь системы инцидентов с базой знаний. Без явной связки postmortem'ы лежат внутри инцидентов, а решение типовых проблем — где-то в Wiki, и при следующем инциденте дежурный их не находит. COSCIO решает это тем, что разрешённые инциденты с заполненным postmortem становятся searchable: при создании нового инцидента система предлагает похожие случаи из истории, и видны не только сами инциденты, но и приложенные к ним playbook'и, которые сработали. Это превращает каждый разобранный инцидент в кирпичик коллективного опыта, который доступен в момент следующей аварии.
MTTR — это не метрика технической команды, это метрика бизнеса. Каждая минута, на которую сокращается среднее время восстановления, конвертируется в сэкономленные деньги: сохранённую выручку, неутрату клиентов, ненанятый дополнительный персонал поддержки. Эти деньги невидимы — никто не ходит к финансовому директору с отчётом "мы сэкономили вам 8 миллионов рублей, ускорив MTTR с 45 до 12 минут". Но они реальны и они там есть. И именно поэтому управление инцидентами заслуживает того же внимания, что и продуктовая разработка, маркетинг, продажи. Это не вспомогательная функция IT — это прямой инструмент управления рисками бизнеса.