Проверка обратных ссылок заблокировала наш релиз: гипотетический разбор инцидента
Вымышленная команда, вымышленный инцидент, реальные механизмы. Мы излагаем события в том порядке, в котором инженер дежурной смены записал бы их в журнал.
Исследовательская команда Contentin ·
Это пример
Команда, продукт и временные рамки ниже вымышлены, чтобы показать, как развивается сбой. Не описывается ни реальная компания, ни клиент, ни какие-либо измерения.
Хронология инцидента
1
09:10, страница запуска попадает в CMS
Шестичленная продуктовая команда поддерживает маркетинговый сайт на headless CMS и статической сборке. Редактор готовит анонс партнерства, содержащий ссылку на домен партнера, зарегистрированный на прошлой неделе.
2
09:14, редактор нажимает «Опубликовать»
Webhook публикации вызывает функцию. Функция выполняет запрос к проверке обратных ссылок для домена партнера и настроена на блокировку релиза при любом неуспешном ответе.
3
09:14, сборка так и не началась
Одновременно происходят два сбоя. Домен новый, поэтому наш индекс может его еще не знать. Кроме того, предоплаченный баланс ключа команды был исчерпан, поэтому платный последующий запрос вернул HTTP 402.
4
09:40, команда обнаруживает проблему
Редактор сообщает о неясной ошибке. Инженер читает логи функции, видит 402 и пустой результат и тратит двадцать минут на выяснение, что именно вызвало блокировку.
5
10:05, запуск происходит вручную
Кто-то обходит хук с помощью ручной деплой-операции. Запуск задерживается на 55 минут, а обход оставляет след: неизвестно, какие проверки были пропущены.
Что команда проверяла перед запуском
Совершенно немного, как оказалось. Список тестов содержал только известные домены, поэтому пробел остался незамеченным до тех пор, пока не появилась партнерская ссылка. Тест на известном сайте доказывает, что инфраструктура работает, но ничего не говорит о домене, который индекс еще не видел.
Хороший список тестов должен включать три типа доменов: устоявшийся, узкоспециализированный и недавно зарегистрированный. Прогоняйте все три через хук, прежде чем доверять ему.
Какие домены покрывал тест?
Только простые. Каждый домен в списке имел многолетнюю историю, поэтому каждый ответ был полным, и никто не видел, как пустой ответ влияет на публикацию.
Добавьте один действительно новый домен и прочитайте его результат вручную. Если в заметке указано «bad» (ошибка), а должно быть «unknown» (неизвестно), правило нужно пересмотреть до запуска.
Что упустила тестовая сборка?
Тестовая сборка использовала ключ с достаточным балансом, поэтому путь с пустым балансом никогда не выполнялся. Никто не написал тест, который намеренно исчерпал бы кредит.
Держите этот путь под тестированием. Раз в квартал искусственно вызывайте 402 и смотрите, что видит редактор после этого, потому что путь сбоя, который никто не проверяет, — это путь, которому никто не доверяет.
Почему это произошло
Шлюз воспринимал любой неуспешный ответ как окончательный вердикт. Это была корневая причина. Проблема с балансом и неизвестный домен — это факты о инструментарии и индексе, и ни один из них ничего не говорит о странице.
Наш граф перестраивается примерно раз в месяц. Домен, зарегистрированный после последнего обновления, может выглядеть пустым, а новый партнер — это нормальный случай для страницы запуска. Никто не проверил это. Команда тестировала хук только со старыми, известными доменами, такими как nytimes.com.
Второй упущенный момент — тишина. Функция записала ошибку, но не отправила оповещение, и редактор увидел общее сообщение об ошибке без намека на то, что кредит исчерпан.
Стоимость никогда не была проблемой. При стоимости 2 кредита за вызов вся месячная проверка для этого вымышленного сайта обошлась примерно в $0.60, та же сумма, что и в строке с 3000 публикациями в таблице стоимости. Шлюз был дешевым, но стоил команде час времени в 2026 году.
402 заслуживает отдельной строки. Предоплаченный баланс — это состояние, которое можно отслеживать, поэтому простой алерт при 10 000 кредитов, что составляет $1, сработал бы за несколько дней до инцидента.
Пункты действий, записанные командой
Владельцы — это роли, а не люди. Все пункты являются частью примера.
Изменение
Владелец
Почему
Воспринимать 402 как пропуск плюс оповещение в канал платформы
Платформа
Кредит — это состояние биллинга, а не состояние страницы
Воспринимать пустой результат для нового домена как unknown (неизвестно), а не как bad (ошибка)
Платформа
Индекс отстает примерно на месяц
Показывать редактору причину простыми словами
Редакторский инструментарий
Потеряно 20 минут на чтение логов
Записывать пропущенные проверки в запись
Платформа
Ручные деплои не оставляли следа
Протестировать хук с доменом, зарегистрированным на этой неделе
QA
Старые домены скрывают пробел
Репетиция перед неделей запуска
Выполните эти действия перед следующим запуском, а не после следующего сбоя.
1
Выбрать домен, который никто не проверял
Выберите недавно зарегистрированный домен и вызовите для него бесплатное действие «Обзор». Подтвердите, что тонкий ответ логируется как unknown (неизвестно), а не как блокировка.
2
Исчерпайте тестовый баланс
Используйте тестовый ключ с небольшим балансом и намеренно доведите его до нуля. Отслеживайте приход 402, срабатывание алерта и продолжение публикации до сборки.
3
Прочитайте сообщение редактора вслух
Попросите коллегу, который не видел хук, прочитать текст ошибки. Если он не может сказать, что делать дальше, перепишите сообщение до запуска.
4
Записывать пропуск в запись
Подтвердите, что пропущенная проверка оставляет датированную заметку в записи с указанием причины. Тогда ручной деплой никогда не оставит пробел, который никто не сможет объяснить.
Как было написано исправление
Команда разделила один общий сбой на три, потому что у каждого ответа свой владелец. 401 — это проблема ключа, 402 — состояние биллинга, а пустой результат для нового домена — это просто unknown (неизвестно). Каждый из них получает свою ветку и свое сообщение. Это и есть все изменение.
Никому не нужно было читать стек вызовов, чтобы понять, что произошло. Имя алерта указывает на состояние, а редактор видит предложение, которое говорит, что делать дальше.
Почему порог срабатывания алерта баланса установлен значительно выше нуля?
Десять тысяч кредитов — это $1 по опубликованной цене, небольшая сумма, которая все же дает достаточно предупреждения при раннем срабатывании. Устанавливайте алерт там, где его увидит человек, а не в логе, который никто не откроет в пятницу.
Проверка, которая громко сигнализирует об ошибке раз в день, лучше, чем тихая, которая дает сбой во время запуска.
Согласуйте число с командой и запишите его в том же месте, что и правило ротации ключей, чтобы они пересматривались вместе.
Должен ли новый домен считаться ошибкой?
Нет. Домен, который индекс еще не видел, — это факт об индексе, а не о странице. Сохраняйте его как unknown (неизвестно) с датой и позвольте редактору решить, ждать ли следующего обновления.
То же правило применяется к любому тонкому ответу. Воспринимайте его как недостающие данные, а не как вердикт о партнере.
Логируйте ответы unknown (неизвестно) в отдельный список, чтобы их паттерн был виден на следующем обзоре, а не был погребен в общем журнале.
Что стоит перенять
Открывайте шлюз при проблемах с данными ссылок, но громко сигнализируйте об оповещениях
Проверка ссылок никогда не должна быть единственным препятствием между редактором и запуском. Пропустите страницу, пометьте запись и сделайте так, чтобы ошибка была очевидна для владельца ключа.
Прорепетируйте сбой на staging-среде перед днем запуска
Вопросы, которые задала команда после инцидента
Совещание по обзору подняло тот же набор вопросов в каждой версии этой истории. Вот как вымышленная команда ответила на них и почему эти ответы могут отличаться в разных организациях.
Ни один из этих ответов не является универсальным, и каждый зависит от назначения страницы. Главное — иметь ответ на бумаге до следующего релиза.
Должен ли был шлюз блокироваться?
Для этой вымышленной команды — нет. Проверка ссылок — это сигнал, основанный на ежемесячном индексе, и он не должен быть единственным препятствием между редактором и запуском.
Запишите политику одним предложением, чтобы следующий инженер мог отличить намеренную блокировку от бага.
Увеличенный баланс предотвратил бы это?
Он отсрочил бы проблему, а не исправил дизайн. Увеличенный баланс тоже может исчерпаться, а шлюз, который воспринимает любой неуспешный ответ как вердикт, все равно заблокирует первый неизвестный домен.
Исправление — это разделение на три ответа плюс алерт, срабатывающий заранее. Баланс — только часть истории.
Задайте тот же вопрос любому шлюзу, который вы строите: какой сбой останется незамеченным, и кто заметит его первым?
Примечание о гипотетическом сценарии
Реальные команды будут отличаться. Ваша команда может блокироваться по уважительным причинам, например, на регулируемом сайте каждая исходящая ссылка проверяется человеком. Отлично. Просто сделайте это осознанным выбором.
В руководстве по webhook те же решения представлены в виде чек-листа, а в списке мифов описаны убеждения, которые привели эту вымышленную команду в ловушку.