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

Почему команды застревают, когда начинают с сервисов
Большинство архитектурных ревью идут не так в первые десять минут. Кто‑то рисует API, очередь, две базы данных и кэш. Потом в комнате начинается спор о инструментах, границах и о том, стоит ли одну коробку разбить на три.
Это кажется продуктивным, потому что диаграмма быстро растёт. Обычно это ловушка.
Команда начинает называть части, прежде чем договорится о том, что может упасть и что этот провал сделает с пользователем или бизнесом. На примере оформления заказа это видно явно. Один человек хочет сервис платежей. Другой — сервис заказов, шину событий и воркер для повторов. Между тем не задают более трудный вопрос: если платёж прошёл, а создание заказа задержалось, кто это заметит, что увидит клиент и как исправить без двойного списания?
Когда начинают с сервисов, дизайн уходит в сторону личных предпочтений. Люди защищают знакомые инструменты. Они спорят о прямых вызовах против очередей, но не называют реальный ущерб: потерянные заказы, поздние письма, дублированные отправления или запись «оплачено», когда ничего не отправлено.
В результате опасные пути остаются за дверью. Чистые диаграммы редко показывают тихие отказы. Сообщение приходит дважды. Таймаут скрывает успех. Повтор обновляет одну таблицу и пропускает другую. Это те пути, что будят людей в 2 часа ночи, но часто получают мало внимания.
Встреча завершается аккуратной картинкой и без жёстких решений. Команда всё ещё не знает, какие действия должны быть атомарными, где важна идемпотентность, что может быть в eventual consistency и какие отказы требуют немедленного алерта.
Лучшее ревью начинается с ущерба, а не с коробок. Спросите, как выглядят потеря, задержка, дублирование и неверное состояние в одном потоке. Когда команда согласует эти риски, диаграмма обычно становится меньше и понятнее. Некоторые блоки исчезают. У других наконец появляется причина существовать.
Четыре режима отказа, которые нужно назвать в первую очередь
Большинство проблем ревью укладывается в четыре простых корзины.
Потеря — самое простое для объяснения и одно из самых лёгких для пропуска. Запрос, событие или обновление исчезают, и никто не замечает, пока что‑то вниз по потоку не пойдёт не так. Пользователь нажимает «Оплатить», а запись заказа так и не появляется. Или обновление запасов исчезает между системами.
Задержка другая. Работа приходит, но слишком поздно, чтобы помочь. Пять секунд могут быть безвредны для письма, но та же задержка сломает удержание товара или проверку на мошенничество. Время важнее, чем многие команды признают.
Дублирование звучит как мелочь, пока в дело не вмешаются деньги или побочные эффекты. То же действие выполняется дважды. Система отправляет два письма, создаёт две отгрузки или списывает ту же карту снова. Если команда не назовёт этот риск рано, она часто построит систему, которая на демо выглядит нормально, но создаёт настоящие боли для поддержки позже.
Неверное состояние самое трудное, потому что ничего явно не выглядит сломанным. Экраны загружаются. Сервисы отчитываются об успехе. Данные существуют. Но рассказ, который данные дают, неверен. Аккаунт отображается как «активный», хотя платёж не прошёл. Запасы выглядят доступными после рассинхронизации двух систем. Поддержка, финансы и клиент видят разные версии реальности.
Эти четыре ярлыка удерживают дискуссию от абстракций:
- Потеря: «Что если оно никогда не придёт?»
- Задержка: «Что если оно придёт слишком поздно?»
- Дублирование: «Что если это случится дважды?»
- Неверное состояние: «Что если каждый шаг прошёл, но итоговая картина неверна?»
Как только люди используют эти слова, ревью быстро улучшается. Вместо споров о Kafka, gRPC или cron jobs они задают лучшие вопросы о повторах, временных лимитах, идемпотентности, владении и путях восстановления.
Простой способ провести ревью
Держите охват узким. Выберите одно действие пользователя, например «клиент оформляет заказ» или «пользователь подаёт запрос на возврат», и пока игнорируйте остальную платформу.
Затем напишите нормальный путь в одном предложении. Сделайте его простым и скучным: «Пользователь отправляет заказ, система снимает деньги с карты, сохраняет заказ и отправляет подтверждение.» Если команда не может согласовать это предложение за две минуты, дизайн уже расплывчат.
Хорошее ревью следует простому порядку. Выбрать действие пользователя. Написать happy path в одном предложении. Спросить, как возможны потеря, задержка, дублирование и неверное состояние. Записать влияние на пользователя для каждого случая. Только затем выбирать контролы.
Порядок важен. Если кто‑то прыгает сразу к «использовать Kafka» или «добавить повторы», остановите комнату и верните её к обсуждению отказа. Спросите, что именно теряется, что приходит с опозданием, что выполняется дважды или что оставляет систему в неправильном состоянии.
Запишите влияние в терминах пользователя до обсуждения инструментов. Задержанное письмо подтверждения раздражает. Отсроченное резервирование товара может продать товар, которого у вас нет. Дублированный платёж хуже обоих: финансы, поддержка и клиент почувствуют это одновременно.
Это меняет тон встречи. Люди перестают защищать любимые технологии и начинают говорить о последствиях. Этот сдвиг приводит к лучшим решениям.
После того как группа согласовала отказ и влияние, выберите контроль, соответствующий проблеме. Для дублирования может понадобиться идемпотентность. Для задержки — таймауты, повторы или экран статуса. Для неверного состояния — сверка данных или ручной путь проверки. Не нужны все меры подряд. Нужны те, что соответствуют ущербу, которого пытаются избежать.
Вопросы, которые держат обсуждение на земле
Хорошие ревью остаются конкретными. Самый быстрый способ — задавать простые вопросы до того, как кто‑то начнёт спорить об очередях, сервисах или хранилищах.
Начните с потери для пользователя. Если этот шаг провалится, что реально потеряет пользователь? Деньги, время, доверие, данные или просто неудобство — это разные уровни. Отправка письма важнее, чем потеря записи оплаты, и в комнате об этом должны честно сказать.
Затем спросите про задержку. Если этот шаг встанет на 30 секунд, 10 минут или 2 часа, когда кто‑то заметит? Некоторую работу можно дождаться ночной повторной попытки. Другая ломает продукт так, что пользователи чувствуют это сразу. Этот временной предел формирует дизайн больше, чем спор об инструментах.
Далее идёт дублирование, которое команды часто пропускают. Если шаг выполнится дважды, получите ли вы два списания, два отправления, два письма или никакого реального вреда? Многие отказы в распределённых системах выглядят обычными сначала. Проблема не всегда в падении — часто это повтор, который тихо делает то же самое снова.
Неверное состояние тоже требует ясного владельца. Спросите, кто первым увидит неправильное состояние. Это может быть клиент на устаревшей странице заказа. Может быть поддержка при всплеске обращений. Может быть финансы, когда итоги перестают сходиться. Узнав, кто замечает первым, вы решаете, где должны быть проверки и что требуется сверять позже.
Затем спросите про сигналы. Что скажет команде, что началась проблема? Рост ошибки, очередь, которая не падает, пропавшие записи, дубликаты или сообщение от клиента — это очень разные сигналы. Если никто не может назвать хотя бы один, ревью всё ещё слишком абстрактно.
Короткое упражнение помогает. Возьмите один шаг в потоке и ответьте на пять подсказок по минуте каждая: что теряет пользователь при сбое, сколько времени можно ждать, что случится при двойном выполнении, кто первым увидит неверное состояние и какой сигнал докажет, что что‑то пошло не так.
Если команда не может ответить на эти вопросы ясно, ещё рано называть сервисы. Группа всё ещё не согласовала риск.
Простой пример с потоком заказа
Клиент покупает последнюю пару кроссовок в вашем магазине. Платёж проходит, запасы должны уменьшиться на одну позицию, заказ должен появиться в системе, и подтверждение должно дойти до клиента. Это звучит рутинно — именно поэтому этот сценарий хорошо работает в ревью.
Начните с потери. Если платёжный провайдер говорит «paid», а приложение никогда не создаёт заказ, клиент видит списание, а у команды нет записи, что отправлять, и нет понятного способа всё исправить.
Задержка бьёт тише. Возможно, заказ существует, но обновления запасов приходят через 10 минут из‑за забивки очереди или медленного цикла повторов. Сайт всё ещё показывает товар доступным, кто‑то другой покупает его, и поддержка вовлекается, когда один из заказов приходится отменять.
Дублирование быстро становится дорогим. Клиент нажимает «Оплатить» дважды из‑за медленного спиннера, или система повторяет запрос без проверки, завершён ли он уже. Теперь карта списана дважды, появляются две записи заказа или склад отправляет один и тот же товар дважды. Многие называют это крайним случаем. На практике его достаточно, чтобы планировать защиту.
Неверное состояние хуже. Оформление показывает, что заказ оплачен, а выполнение считает его неоплаченным. Финансы видят одни статусы, склад — другие, а клиент уже получил письмо с подтверждением. Ничто полностью не потеряно, но никто не может сказать, что правильно.
Здесь ревью становится острее. Вместо спора о названиях сервисов команда задаёт конкретные вопросы. Какому шагу нужен идемпотентный токен? Когда менять запас? Какая система владеет финальным ответом «оплачен»? Что видит клиент, если платёж прошёл, но создание заказа упало?
Если команда не может объяснить, как она обнаруживает потерю, ограничивает задержку, блокирует дублирование и ремонтирует неверное состояние, дизайн ещё слишком ранний.
Ошибки, которые превращают ревью в трату времени
Первая ошибка — начинать с инструментов. Кто‑то говорит «очередь, кэш, webhook, воркер и read replica», прежде чем кто‑то назовёт реальную потерю. Это звучит конкретно, но скрывает разногласия. Один думает о потерянных данных, другой о медленных обновлениях, третий — о дублировании. Они могут полчаса обсуждать и всё равно говорить о разных проблемах.
Ещё одна распространённая ошибка — смешивать задержку с потерей. Это не одно и то же. Если подтверждение заказа приходит с опозданием в 20 минут, вам нужны правила повторов, таймауты или понятный экран статуса. Если подтверждение никогда не приходит, нужен другой способ исправления. Если оно приходит дважды, нужны идемпотентность или дедупликация. Когда всё это сваливают под «надёжность», обсуждение расплывается, а дизайн остаётся неясным.
Расплывчатые ярлыки усугубляют ситуацию. Фразы вроде «проблема консистентности» или «крайний случай» звучат умно, но не говорят команде, что именно может сломаться. Лучше сформулировать жёстко: «Клиент заплатил, но заказа нет». Или: «Отправление создано дважды». Или: «Поддержка не может понять, запускался ли повтор».
Команды также ограничиваются обнаружением и пропускают восстановление. Это дорого обходится. Система может заметить неверное состояние, и при этом оставить сотрудников без безопасного способа его исправить. Ручная работа здесь важна.
Задайте несколько прямых вопросов. Кто видит проблему первым: клиент, поддержка или система? Что человек может сделать за пять минут, чтобы уменьшить ущерб? Какая запись доказывает правильное состояние? Кто пишет шаг повторов, бэкофилла или очистки? Кто владеет последующими действиями после релиза?
Последняя ошибка проста: никто не уходит с владением. Ревью без владельцев — это просто разговор с диаграммами. Назначьте для каждого режима отказа одного человека, одно следующее действие и дату. Если никто не владеет путём повторов, алертом или инструкцией для поддержки, та же проблема появится снова на следующей встрече.
Как превратить режимы отказа в архитектурные решения
Ревью становится полезным, когда каждый режим отказа приводит к одному ясному проектному ответу. Не останавливайтесь на «это может провалиться». Решите, что система будет делать при отказе, как быстро она должна среагировать и кто получает уведомление.
Простой дефолт работает хорошо. Для потери — сохраните намерение до начала работы или держите долговременную запись о том, что действие произошло. Для задержки — установите временной лимит, решите, что происходит после его истечения, и оповестите команду, если задержка меняет результат. Для дублирования — добавьте проверки на дубликаты, чтобы повторы и повторные клики не создавали одно и то же действие дважды. Для неверного состояния — определите шаг восстановления при частичном сбое, например повтор, откат или пометка записи для ручной проверки.
Держите ответ простым. Если команда называет три контроля на один маленький риск, это обычно значит, что группа не доверяет ни одному из них.
Задержке нужно уделить дополнительное внимание, потому что медленные системы часто выглядят нормально, пока деньги, запасы или доверие клиентов не начнут ускользать. Пропишите числа. Если задача безвредна при 10 секундах, но вредна при 2 минутах, запишите это. Потом поставьте таймаут и алерт на этот порог, а не где‑то дальше.
Частичный сбой требует самого ясного правила. Напишите одно предложение, которое говорит, что система делает, если шаг первый сработал, а шаг второй нет. Например: сохранить первый результат, пометить запись как неполную и повторять шаг два в течение 15 минут, прежде чем отправить на ручную проверку. Это гораздо лучше, чем «обрабатывать ошибки аккуратно».
Делаем результаты пригодными для переиспользования
Записи должны быть короткими, чтобы их можно было вставить в следующее ревью без доработок. Компактный формат работает хорошо: режим отказа, триггер, ответ, владелец и алерт.
Если заметка не помещается в несколько строк, она, вероятно, всё ещё слишком расплывчата или сложна. Короткие записи также упрощают пересмотр компромиссов позже, когда система меняется.
Быстрый чеклист перед окончанием встречи
Хорошее ревью должно закончиться простыми ответами, а не облачком на диаграмме, которое каждый трактует по‑своему. Если люди всё ещё спорят о названиях сервисов, но не могут сказать, какой отказ вредит бизнесу сильнее, остановитесь и сузьте обсуждение.
Перед завершением убедитесь, что группа может сформулировать самый большой риск потери в одном предложении. Поставьте реальный временной лимит на вредные задержки. Решите, как система блокирует двойную обработку. Проверьте неверное состояние, а не только отсутствие данных. Уходите с владельцами и следующими действиями.
Одна маленькая привычка очень помогает: проговорите эти ответы вслух. Слабые места становятся очевидны быстро. «Мы как‑то справимся с дублями» — это не решение. «Сэм добавит идемпотентность на callbacks платежей до пятницы» — это решение.
Эта часть ревью должна быть немного строгой. Это хороший знак. Команда, которая может простыми словами назвать потерю, задержку, дублирование и некорректные данные, обычно строит чище системы и тратит меньше времени на последующие встречи.
Что делать дальше с вашей командой
Выберите один поток, который уже причиняет боль пользователям или создаёт ручную очистку. Хорошие кандидаты: оформление заказа, регистрация, сброс пароля, генерация счёта — всё, что ведёт к возвратам, дублированным записям или тикетам в поддержку. Если боль реальна, люди остаются сфокусированными, потому что могут представить ущерб.
Держите первую встречу короткой. 30 минут достаточно. Используйте одну белую доску или общий холст и пройдите поток простыми шагами. Запишите, что происходит сначала, что меняет данные, что отправляет сообщения и что видит пользователь.
Затем задайте трудные вопросы до того, как кто‑то начнёт называть сервисы. Где работа может потеряться? Где она может появиться с опозданием? Где она может выполниться дважды? Где система может оказаться в неверном состоянии? Это та часть, которую многие команды пропускают, и она причина, по которой ревью часто превращается в дебаты о диаграммах вместо проектных решений.
Ждите с рисованием диаграммы сервисов до конца. Команды теряют время, когда сразу прыгают к коробкам, стрелкам, очередям и границам репозиториев. Как только режимы отказа на доске, диаграмма становится меньше и полезнее. Вы уже не догадываетесь, что дизайн должен делать — вы спрашиваете, как он предотвращает конкретную проблему.
Практическая первая сессия проста: выберите один пользовательский поток с недавней болью, опишите поток простым языком, отметьте потерю, задержку, дублирование и неверное состояние на каждом шаге, набросайте сервисы только после того, как риски видны, и уйдите с одним владельцем и одним тестом для самого рискованного места.
Если ваша команда снова и снова вращается в одних и тех же абстрактных спорах, внешний обзор может помочь. Oleg Sotnikov на oleg.is работает со стартапами и небольшими командами в роли Fractional CTO, помогая превращать расплывчатые разговоры об архитектуре в конкретные решения по обработке отказов, системам и доставке.
После встречи протестируйте одно исправление в том же потоке в течение недели. Даже небольшое изменение, например проверка идемпотентности или правило таймаута, даст больше знаний, чем ещё одно длинное ревью.
Часто задаваемые вопросы
Почему обзор должен начинаться с режимов отказа, а не с сервисов?
Потому что рамки сервисов скрывают реальный риск. Если начать с потерь, задержек, дублирования и неверного состояния, команда сначала говорит о вреде для пользователя и выбирает меры для реальной проблемы, а не защищает любимые инструменты.
Какие это четыре режима отказа простыми словами?
Потеря — значит что-то никогда не приходит или не сохраняется. Задержка — значит приходит слишком поздно. Дублирование — одно и то же действие выполняется дважды. Неверное состояние — все шаги кажутся успешными, но итоговые данные дают неправильную картину.
Как провести короткое архитектурное ревью, чтобы оно не превратилось в спор об инструментах?
Выберите одно действие пользователя и опишите обычный путь в одном предложении. Затем спросите, как этот поток может потеряться, прийти с опозданием, выполниться дважды или закончиться в неверном состоянии. После того как команда согласует ущерб, выберите контроль, владельца и алерт.
В чём разница между потерей и задержкой?
Потеря означает, что система роняет работу и её нельзя восстановить позже. Задержка означает, что работа всё же приходит, но по времени это уже нанесло вред. Эта разница меняет способ исправления: утерянная работа требует долговременной записи или шага восстановления, а медленная — таймаутов, повторных попыток или более явного статуса для пользователя.
Почему дублирование вызывает столько проблем?
Повторы, двойные клики и таймауты приводят к этому регулярно. Один дубликат может дважды списать деньги, создать два отправления или завалить поддержку ручной очисткой. Команды должны рассматривать обработку дубликатов как нормальную часть дизайна, а не как редкий крайний случай.
Как выглядит неверное состояние в реальном продукте?
Неверное состояние проявляется, когда системы расходятся во мнениях о том, что истинно. Страница оформления может показывать «оплачено», в то время как исполнение считает «не оплачено», или бухгалтерия видит итоги, не совпадающие с заказами. Нужен один источник правды и шаг восстановления, когда части потока расходятся.
Когда стоит обсуждать очереди, сервисы и хранилища?
Подождите, пока команда не сможет назвать отказ, влияние на пользователя и допустимый предел времени. Когда эти ответы есть, инструменты легче оценивать. Очередь, прямой вызов или cron имеют смысл только если вы знаете, какой именно вред пытаетесь предотвратить.
Что команда должна записать перед окончанием встречи?
Уходите с конкретными решениями, а не только с диаграммой. Запишите самую большую угрозу одной фразой, контроль для неё, кто отвечает за следующий шаг и когда команда его протестирует. Если никто не владеет путём повторов, алертом или шагом очистки, проблема вернётся снова.
Какой первый поток хорошо разобрать с командой?
Выбирайте поток, который уже причиняет боль пользователям или создаёт ручную очистку. Checkout, возвраты, регистрация, сброс пароля и генерация счетов — хорошие кандидаты, потому что люди быстро представляют ущерб. Держите первую сессию короткой, чтобы команда сосредоточилась на одном сценарии.
Когда имеет смысл приглашать внешнего эксперта для ревью архитектуры?
Привлекайте внешнего эксперта, когда команда всё время возвращается к тем же абстрактным спорам или выпускает правки, которые не решают реальную проблему. Опытный Fractional CTO может направить обсуждение к конкретным решениям, распределению ответственности и практическим мерам для самого болезненного потока.