Постмортем инцидента для публикации

Превращает внутренний разбор аварии в публичный постмортем: хронология, настоящая причина вместо «человеческого фактора», выводы без самобичевания и без корпоративного тумана.

// промпт
Ты — инженер, который писал публичные постмортемы и читал сотни чужих. Ты знаешь, что хороший постмортем не ищет виноватого и не прячет суть за формулировками вроде «произошёл сбой в работе сервиса». Ты требуешь конкретики и вычищаешь пассивный залог, за которым исчезает субъект. Помоги превратить внутренний разбор в текст, который можно опубликовать. **Параметры** - Что случилось, своими словами: {{opisanie_incidenta}} - Хронология с временами: {{xronologiia}} - Что увидели пользователи: {{vliianie_na_polzovatelei}} - Как чинили: {{deistviia_po_ustraneniiu}} - Что уже поменяли после: {{priniatye_mery}} - Насколько открыто можно писать: {{uroven_otkrytosti}} **Как действовать** 1. Восстанови хронологию в едином формате: время, событие, кто или что его вызвало, кто его заметил. Отдельно отметь два интервала — от начала проблемы до её обнаружения и от обнаружения до устранения. Первый обычно неприятнее и важнее второго. 2. Отдели симптом от причины. «Упал сервис» — симптом. «Закончились соединения в пуле» — тоже ещё симптом. Копай до решения или условия, которое сделало отказ возможным. 3. Проверь причину вопросом «почему» несколько раз подряд, но остановись там, где ответ становится «потому что люди несовершенны». «Человеческий фактор» — это не причина, а место, где расследование прекратили раньше времени. 4. Опиши влияние честно и измеримо: сколько пользователей, какие операции, потеряны ли данные, был ли ущерб необратимым. Если данные потеряны — это должно быть сказано прямо и рано, а не спрятано в середине. 5. Раздели меры на три группы: что уже сделано, что делается сейчас, что запланировано и когда. Обещания без срока лучше не включать вовсе — их отсутствие заметят. 6. Вычисти обезличивающие обороты. Замени «было принято решение» на «мы решили», «произошёл сбой» на конкретное описание. Покажи мне список того, что заменил. 7. Проверь текст на то, чего в нём быть не должно: имён сотрудников, обвинений подрядчика, внутренних адресов и идентификаторов, оценок вроде «к счастью, всё обошлось». **Формат ответа** Готовый текст постмортема с заголовками, затем отдельным блоком — замечания редактора: что я смягчил и почему, где не хватает данных, что стоит перепроверить перед публикацией.
Заполните переменные

Пример запуска

Сгенерировано Claude Opus 5.5, 24 сентября 2026 г.

Значения переменных

Описание инцидента
15 сентября в 08:58 по московскому времени была выкачена версия 2.14.0 бэкенда Ledgerly. В рамках деплоя обновлялся конфиг PgBouncer, и по ошибке в шаблоне значение max_client_conn откатилось с 500 до дефолтных 50. Из-за этого при обычном утреннем всплеске нагрузки (у нас пик входящих запросов приходится на 09:00–09:15 МСК, когда бухгалтеры открывают сервис в начале рабочего дня) пул соединений к базе оказался исчерпан. Начался массовый рост 502 и 504 на API-гейтвее. Был затронут в первую очередь эндпоинт создания счетов и генерации PDF, а также обработка вебхуков для интеграций с 1С и Контур.Диадоком. Сбой был замечен дежурным инженером по алерту на error rate в 09:04, после чего было принято решение откатить деплой. Дополнительно оказалось, что часть клиентских SDK при таймауте автоматически ретраили запрос на создание счёта, из-за чего у части пользователей задвоились записи — это пришлось разгребать руками после восстановления. Данные не потеряны, но по 180 счетам потребовалась ручная сверка и удаление дублей.
Хронология
08:58 — выкачен релиз 2.14.0, конфиг PgBouncer заменён (max_client_conn 500→50, ошибка в шаблоне). 09:00 — начало обычного утреннего пика нагрузки. 09:02 — рост 5xx на API. 09:04 — сработал алерт по error rate, дежурный инженер взял инцидент в работу (это и есть момент обнаружения — 6 минут от начала проблемы). 09:09 — объявлен инцидент SEV1 в статус-канале, подключены бэкенд-разработчик и DBA. 09:14 — принято решение откатывать релиз, а не чинить конфиг на лету. 09:19 — начат роллбэк 2.14.0 через CI/CD. 09:31 — роллбэк завершён, конфиг PgBouncer восстановлен вручную. 09:36 — error rate и латентность вернулись к норме (22 минуты от обнаружения до устранения). 09:50 — инцидент закрыт как technically resolved. 09:50–13:00 — ручная сверка задвоенных счетов и разбор отставшей очереди вебхуков.
Влияние на пользователей
Около 14 000 из 22 000 активных аккаунтов получали 502/504 при создании счетов и генерации PDF в течение 38 минут (09:02–09:40). У 3 200 подписчиков вебхуков (интеграции с 1С и Контур.Диадоком) доставка событий задержалась до 40 минут, очередь полностью догналась только к 12:40. Из-за автоматических ретраев в клиентских SDK у 180 пользователей задвоились записи о счетах; данные не потеряны, но потребовалась ручная сверка и удаление дублей, что заняло у саппорта весь день 15 сентября.
Действия по устранению
09:04 дежурный инженер подтвердил деградацию по дашборду error rate. 09:09 объявлен SEV1, подключены разработчик бэкенда и DBA. 09:14 решили откатывать релиз 2.14.0, а не чинить конфиг на лету. 09:19–09:31 выполнен роллбэк через CI/CD и вручную возвращено значение max_client_conn=500 в PgBouncer. 09:36 подтверждена нормализация error rate и латентности. До 13:00 саппорт вручную сверял задвоенные счета по логам и удалял дубли, клиентам с задвоением отправлены индивидуальные письма с извинениями.
Принятые меры
Уже сделано (к 18 сентября): в CI добавлена проверка diff конфигов PgBouncer, блокирующая деплой при отклонении от согласованных значений; на дашборд добавлен алерт на падение доли свободных соединений в пуле ниже 15%. В процессе: пишем ранбук по инцидентам с пулом соединений (готовность — 1 октября 2026). Запланировано: перевод конфигурации инфраструктурных сервисов (PgBouncer, Redis) на canary-раскатку с автооткатом по метрикам ошибок — срок 15 октября 2026; увеличение дефолтного размера пула с запасом x2 под пиковую нагрузку — срок 30 сентября 2026.
Уровень открытости
Публикуем на публичной странице статуса и в блоге компании для всех клиентов и партнёров. Можно называть технические детали, метрики и полный таймлайн, но без имён сотрудников, без упоминания конкретных клиентов с задвоенными счетами и без финансовых оценок ущерба.

Постмортем: ошибки при создании счетов и задержка вебхуков 15 сентября 2026 года

Опубликовано: [дата публикации]

Кратко

15 сентября с 09:02 до 09:40 МСК около 14 000 из 22 000 активных аккаунтов Ledgerly (примерно 64%) не могли создавать счета и генерировать PDF: API возвращал ошибки 502 и 504. Доставка вебхуков в интеграции с 1С и Контур.Диадоком задержалась, и очередь полностью разобралась только к 12:40.

Данные не потеряны. Из-за автоматических повторных запросов у 180 пользователей появились дубли счетов. Мы нашли и удалили их вручную, каждому из этих пользователей написали отдельно.

Причина: в 08:58 мы выкатили релиз 2.14.0. Он изменил конфигурацию PgBouncer, прокси между нашим приложением и базой данных PostgreSQL. В новом шаблоне конфигурации лимит клиентских соединений (max_client_conn) был равен 50 вместо прежних 500. Через две минуты начался ежедневный утренний пик нагрузки, лимита не хватило, и PgBouncer перестал принимать новые соединения.

Мы приносим извинения всем, у кого утро 15 сентября началось с ошибок, и особенно тем, кому пришлось разбираться с дублями.

Что увидели клиенты

Что Сколько клиентов Когда Последствия
Ошибки 502/504 при создании счетов и генерации PDF ≈14 000 из 22 000 активных аккаунтов 09:02–09:40 (38 минут) Операции не выполнялись, их нужно было повторить
Задержка доставки вебхуков в 1С и Контур.Диадок 3 200 подписчиков С 09:02, очередь разобрана к 12:40 События доставлены с опозданием, ни одно не потеряно
Дубли счетов 180 пользователей Возникли во время сбоя, удалены 15 сентября Данные не потеряны, дубли удалены вручную, каждому пользователю мы написали

Хронология

Всё время указано по Москве (UTC+3), 15 сентября 2026 года.

Время Событие Причина или инициатор Кто или что заметило
08:58 Мы выкатили релиз 2.14.0. Вместе с ним применился новый конфиг PgBouncer с max_client_conn = 50 вместо 500 Плановый деплой, ошибочное значение в шаблоне конфигурации Никто: проверки значений конфигурации в пайплайне не было
09:00 Начался ежедневный пик нагрузки: бухгалтеры открывают сервис в начале рабочего дня Обычная нагрузка —
09:02 PgBouncer упёрся в лимит 50 соединений. API начал возвращать 502/504 Исчерпан лимит клиентских соединений Клиенты (ошибки в интерфейсе и интеграциях)
09:02 → Клиентские SDK начали автоматически повторять запросы на создание счёта после таймаута Логика повторов в SDK Никто до восстановления сервиса
09:04 Сработал алерт по доле ошибок. Дежурный инженер взял инцидент и подтвердил деградацию по дашборду Мониторинг Алерт по error rate
09:09 Дежурный объявил инцидент уровня SEV1 и подключил бэкенд-разработчика и администратора баз данных Дежурный инженер —
09:14 Мы решили откатить релиз целиком, а не исправлять конфиг на работающей системе Команда инцидента —
09:19 Мы запустили откат 2.14.0 через CI/CD Команда инцидента —
09:31 Откат завершился. Значение max_client_conn = 500 мы вернули в PgBouncer вручную Команда инцидента —
09:36 Доля ошибок и время ответа API вернулись к обычным значениям — Мониторинг
09:40 Последние ошибки 502/504 у клиентов — Логи API-гейтвея
09:50 Мы закрыли техническую часть инцидента. Работа с последствиями продолжилась Команда инцидента —
09:50–12:40 Очередь вебхуков постепенно разбиралась — Мониторинг очереди
09:50–[время] Поддержка по логам нашла дубли счетов у 180 пользователей, удалила их и написала каждому пользователю Команда поддержки Анализ логов после восстановления

Ключевые интервалы

  • От изменения до обнаружения: 6 минут (08:58 → 09:04). От первых ошибок у клиентов до алерта прошло 2 минуты (09:02 → 09:04). Мы узнали о проблеме по симптому, то есть по ошибкам. Сигнала о её причине, заполнении пула соединений, у нас не было.
  • От обнаружения до устранения: 32 минуты (09:04 → 09:36). Основное время ушло на три этапа: 10 минут до решения об откате (09:04 → 09:14), 5 минут до его запуска (09:14 → 09:19) и 12 минут на сам откат, включая ручное исправление конфига (09:19 → 09:31).
  • Полное устранение последствий: вебхуки к 12:40, дубли счетов к [время].

Обнаружение в этом инциденте сработало быстро. Слабым местом оказались сроки реакции: путь от алерта к действию и продолжительность отката.

Почему это произошло

Симптом. API-гейтвей отдавал 502 и 504 на создание счетов, генерацию PDF и обработку вебхуков.

Почему? Запросы не получали соединения с базой: PgBouncer отказывал новым клиентам или держал их в ожидании дольше таймаута гейтвея.

Почему? Лимит клиентских соединений PgBouncer был 50. В обычный утренний пик нам нужно значительно больше, поэтому до этого релиза лимит составлял 500.

Почему лимит стал 50? Релиз 2.14.0 заменил конфигурацию PgBouncer, сгенерированную из шаблона. В шаблоне для max_client_conn стояло значение 50, а не 500. [Уточнить механизм: параметр пропал из шаблона и подставилось значение по умолчанию, в шаблоне была устаревшая версия или переменная не прокинулась в окружение.]

Почему ошибка дошла до продакшена?

  1. В пайплайне не было проверки, которая сравнивает параметры инфраструктурной конфигурации с согласованными значениями. Изменение, которое уменьшило лимит в 10 раз, прошло без предупреждения.
  2. Конфигурация PgBouncer применилась сразу на весь продакшен. Постепенной раскатки, на которой проблема проявилась бы на части трафика, не было.
  3. Релиз вышел в 08:58, за две минуты до ежедневного пика нагрузки. У нас не было правила, запрещающего выкатывать изменения инфраструктуры перед пиком.

Почему последствия оказались тяжелее простого простоя? 4. Эндпоинт создания счёта не защищён от повторов: он не принимает ключ идемпотентности и не распознаёт повторный запрос. Клиентские SDK после таймаута автоматически отправляли запрос ещё раз. Часть исходных запросов при этом успела выполниться на сервере, хотя клиент получил таймаут. Так появились дубли. [Проверить, что механизм именно такой.] 5. Откат релиза через CI/CD не вернул прежнюю конфигурацию PgBouncer, и её пришлось исправлять вручную. [Проверить.] Это удлинило восстановление.

Ни на одном из этих шагов ответ не сводится к тому, что «кто-то ошибся». Ошибка в шаблоне возможна всегда. Проблема была в том, что между ошибкой и продакшеном не стояло ни одной проверки, а сам сервис не был готов к повторным запросам.

Что мы изменили и изменим

Уже сделано (к 18 сентября)

  • Проверка конфигурации в CI. Пайплайн сравнивает конфигурацию PgBouncer с согласованными значениями и блокирует деплой, если они расходятся.
  • Алерт на заполнение пула. Мы получим сигнал, когда доля свободных соединений упадёт ниже 15%, то есть до того, как клиенты начнут видеть ошибки.

В работе

  • Инструкция для дежурных по инцидентам с пулом соединений. В ней будут признаки, порядок диагностики и критерии выбора между откатом и исправлением на месте. Срок: 1 октября 2026 года.

Запланировано

  • Запас по размеру пула. Поднимем лимит соединений с двукратным запасом относительно пиковой нагрузки. Срок: 30 сентября 2026 года.
  • Постепенная раскатка инфраструктурных конфигураций. PgBouncer и Redis будем обновлять сначала на части трафика, с автоматическим откатом при росте ошибок. Срок: 15 октября 2026 года.

Если вас это затронуло

  • Если вы создавали счёт между 09:02 и 09:40 и получили ошибку, проверьте, что счёт существует. Если его нет, создайте заново.
  • Если в вашем аккаунте были дубли, мы написали вам отдельно, и лишние записи уже удалены.
  • Если вы видите расхождения в данных 1С или Диадока за 15 сентября, напишите в поддержку: [контакт].

Замечания редактора

Список замен

Было Стало Зачем
«была выкачена версия 2.14.0» «мы выкатили релиз 2.14.0» Появился субъект
«по ошибке в шаблоне значение откатилось» «в новом шаблоне конфигурации лимит был равен 50» «Откатилось» звучит так, будто значение изменилось само. На деле его изменил наш релиз
«пул соединений к базе оказался исчерпан» «PgBouncer упёрся в лимит 50 соединений и перестал принимать новые» Конкретный механизм вместо «оказался»
«начался массовый рост 502 и 504» «API начал возвращать 502/504» Ясно, кто возвращал ошибки
«был затронут эндпоинт…» «клиенты не могли создавать счета и генерировать PDF» Описано, что видел пользователь
«сбой был замечен дежурным инженером по алерту» «сработал алерт, дежурный инженер взял инцидент» Разделены два события: алерт и реакция человека
«было принято решение откатить деплой» «мы решили откатить релиз целиком» Субъект, плюс сохранена альтернатива, которую отвергли
«подключены бэкенд-разработчик и DBA» «дежурный подключил…» Субъект
«часть клиентских SDK ретраили» «SDK автоматически повторяли запросы» + причина в разделе «Почему» Ответственность не перекладывается на клиентов (см. ниже)
«задвоились записи» «появились дубли счетов» Нейтрально и понятно без жаргона
«пришлось разгребать руками» «поддержка по логам нашла и удалила дубли» Конкретное действие
«инцидент закрыт как technically resolved» «закрыли техническую часть, работа с последствиями продолжилась» Без жаргона. Честно сказано, что для клиентов инцидент на этом не закончился
«выполнен роллбэк» / «подтверждена нормализация» «мы запустили откат» / «вернулись к обычным значениям» Субъект
«клиентам отправлены письма» «мы написали каждому пользователю» Субъект
«в CI добавлена проверка» «пайплайн сравнивает… и блокирует деплой» Описано, что именно делает мера

Что смягчил и почему

  • Слово «ошибка» применительно к шаблону. Я не писал, кто или что её внёс, и перенёс акцент на отсутствие проверок. Это не прячет суть: сам факт ошибки в шаблоне назван прямо.
  • SDK. Если это ваши SDK (судя по контексту, да), формулировка «часть клиентских SDK» читается как «виноваты клиенты». Я перенёс ответственность на сервер без идемпотентности. Если SDK сторонние, формулировку нужно поменять, но корневая причина остаётся той же.
  • Извинение оставил коротким и без самобичевания. Обороты вроде «к счастью, данные не пострадали» я не использовал: отсутствие потерь указано как факт.

Расхождения в исходных данных (исправить до публикации)

  1. «22 минуты от обнаружения до устранения» не сходятся с таймлайном. С 09:04 до 09:36 прошло 32 минуты. Число 22 получается от решения об откате (09:14) до 09:36. В тексте стоит 32. Публичный читатель пересчитает сам.
  2. «6 минут от начала проблемы» считаются от деплоя, а клиенты видели ошибки с 09:02, то есть алерт сработал через 2 минуты. Я привёл оба интервала. Здесь цифры в вашу пользу, и их стоит показать.
  3. Ошибки нормализовались в 09:36, а влияние на клиентов указано до 09:40. Объясните эти 4 минуты (кэш, повторы, долгие запросы) или выровняйте время.
  4. Вебхуки. В исходнике сказано «задержка до 40 минут» и одновременно «очередь догналась к 12:40». Это 3,5 часа. Одно из двух неверно. Возможно, 40 минут составляла задержка для большинства, а хвост разбирался дольше. Тогда так и напишите.
  5. Дубли. В одном месте сверка шла «до 13:00», в другом заняла у поддержки «весь день». Нужно одно время окончания, в тексте стоит плейсхолдер.

Где не хватает данных

  • Почему в шаблоне оказалось 50. Это самое важное недостающее звено. Сейчас разбор останавливается на «ошибке в шаблоне». Кстати, у самого PgBouncer значение max_client_conn по умолчанию равно 100, а не 50, так что «дефолт 50», скорее всего, ваш собственный. Выясните, откуда он взялся.
  • Доля ошибочных запросов. «14 000 аккаунтов получали ошибки» не говорит, падал ли каждый запрос или каждый пятый. Одна цифра («до N% запросов на создание счёта завершались ошибкой») сделает раздел о влиянии заметно сильнее.
  • Не отправлены ли дубли контрагентам. Если повторный счёт успел уйти через вебхук в Диадок или 1С, удаления у вас недостаточно: документ уже у контрагента. Проверьте это первым делом. Если такие случаи были, о них нужно написать прямо и в начале.
  • Обновлялась ли публичная статус-страница во время инцидента и когда. SEV1 объявили в 09:09 во «внутреннем статус-канале». Клиенты спросят, когда об инциденте узнали они.

Пробелы в мерах, которые заметят

  • Нет меры против дублей. Это главная дыра. Вы описали, как дубли появились, но ничего не обещаете, чтобы это не повторилось. Любой технический читатель спросит про ключ идемпотентности на создании счёта и про политику повторов в SDK. Без срока не публикуйте, но решите этот вопрос до выхода текста: пусть в разделе будет хотя бы «ключ идемпотентности для создания счетов, срок такой-то».
  • Нет меры про время деплоя. Релиз вышел за 2 минуты до пика. Правило вроде «никаких изменений инфраструктуры с 08:30 до 10:00» стоит почти ничего, а без него раздел «Почему» выглядит незавершённым.
  • Откат не вернул конфиг (если это так). Мера про постепенную раскатку это частично закрывает, но стоит отдельно сказать, что откат релиза теперь возвращает и инфраструктурную конфигурацию.
  • «Пул с запасом x2». Уточните, какой параметр вы меняете: max_client_conn или default_pool_size. Это разные вещи, и увеличение второго упирается в max_connections PostgreSQL. Сейчас мера сформулирована расплывчато.

Проверка на лишнее

  • Имён сотрудников нет, только роли: дежурный инженер, администратор баз данных, поддержка.
  • Конкретных клиентов нет. 180 названо числом.
  • Финансовых оценок нет.
  • Подрядчиков нет, 1С и Контур упомянуты только как направления интеграций, без претензий к ним.
  • Внутренних адресов, хостов и идентификаторов нет. Имя параметра max_client_conn оставил: это публичная настройка PgBouncer, а не ваш идентификатор.
  • Перед публикацией уберите маркеры [уточнить] и [проверить] и заполните плейсхолдеры: дату публикации, время окончания работы с дублями, контакт поддержки.

Похожие промпты

Социальные сети и Коммуникация

Структура технической статьи для Хабра

Собирает план технической статьи под аудиторию Хабра: заход, который не выглядит рекламой, честная структура разбора и места, где нужны детали, а не общие слова.

Социальные сети и Коммуникация

Разбор дискуссии в треде: аргументы сторон

Разбирает длинный спор в X: кто что утверждает, какие аргументы опираются на факты, где стороны спорят о разном и в чём они на самом деле согласны.

Социальные сети и Коммуникация

Анализ трендов в X по теме

Разбирает, что обсуждают в X по вашей теме прямо сейчас: сюжеты, тональность, кто задаёт тон, где органика, а где накрутка.

Социальные сети и Коммуникация

Вирусные посты для Telegram-канала

Пишет посты для Telegram-канала с высоким потенциалом пересылок: цепляющие первые строки, проверенные виральные форматы и призывы, которые запускают репосты.