Перейти к содержанию

Workflow: проектирование системы от начала до конца#

Двенадцать шагов от «пришла задача» до «дизайн принят». Порядок не ритуальный: каждый шаг производит артефакт, который нужен следующему. Пропуск шага не экономит время — он переносит стоимость ошибки в код.

Документ описывает процесс. Механики (что такое шардирование, как работает Kafka) лежат в карточках topics/, ссылки стоят на каждом шаге.

flowchart TD
    W0[W0 · Требования] --> W1[W1 · Оценки]
    W1 --> W2[W2 · Контракты]
    W2 --> W3[W3 · Данные]
    W3 --> W4[W4 · Архитектура]
    W4 --> W5[W5 · Масштабирование]
    W5 --> W6[W6 · Согласованность]
    W6 --> W7[W7 · Надёжность]
    W7 --> W8[W8 · Безопасность]
    W8 --> W9[W9 · Эксплуатация]
    W9 --> W10[W10 · Стоимость и trade-offs]
    W10 --> W11[W11 · Design review + ADR]
    W5 -.пересчёт.-> W1
    W6 -.меняет модель.-> W3
    W11 -.новые требования.-> W0

Итеративность. Первый проход делается быстро и грубо: W0→W4 за один присест, потом W5→W7 показывают, что оценки или модель данных не сходятся, и вы возвращаетесь. Нормальный дизайн — два-три круга, а не один идеальный проход.

Быстрый проход (интервью, 45 минут). W0 (5 мин) → W1 (5) → W2 (5) → W3 (10) → W4 (10) → W5/W6 точечно по узким местам (10). W7–W11 — только упоминанием, если спросят.

Стадия системы и шаги. Шаги и их порядок одинаковы на всех стадиях — ни один из четырёх прогонов не исключил ни одного шага. Различается наполнение. Блок «по стадиям» стоит только там, где стадия меняет то, что шаг делает, — на пяти шагах из двенадцати: W0, W1, W3, W4, W9. У остальных семи стоит строка «на всех стадиях одинаково», и это не заглушка: пустой блок «здесь ничего особенного» — приглашение заполнить его чем-нибудь.

Граница проведена так: если стадия меняет как читается правило внутри документа, это дело документа — его поля «Стадия» и правил мастер-шаблона, — а не блока в шаге. Два ближайших промаха названы, чтобы граница была видна. На W2 знание о потребителях на гринфилде закладывается, а не покупается; на W5 узкое место нечем подтвердить замером. Оба меняют чтение D-11 и D-03, но не меняют работу шага.

«Под изменением» отдельной колонки не имеет — это режим работающей системы, и всё сказанное про неё действует и там. Своё появляется только у W3, где шаг раздваивается, и у W9.


W0 · Рамки и требования#

Документы шага: D-10 гринфилд · работающая

По стадиям.

Стадия Что меняется на этом шаге
гринфилд Требований не у кого спросить наблюдением: поведения нет. Инварианты и цели назначаются и становятся фактом потому, что так записали. Обещание и измеритель расходятся во времени: сначала строится измеритель, потом даётся обещание, а до первого трафика цель остаётся прогнозом
работающая Половина требований читается из поведения: что уже обещано по умолчанию, что ломается, на что жалуются. Измеритель чаще всего есть, и вопрос в том, с чьей он точки зрения

Различие частичное: набор вопросов шага один и тот же, расходится источник ответов — и вместе с ним пометка в ячейке.

Цель. Понять, что строим и по каким числам поймём, что оно работает.

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

Числа в нефункциональных требованиях — это обещание, и у него должен быть измеритель. Какую цель ставить, чем её мерить и сколько стоит измерение — D-10 · Цели уровня обслуживания и их измерение. Правило оттуда простое: обещать можно только то, что уже измеряется; всё остальное — план построить измеритель, а не цель.

Вопросы, на которые надо ответить.

  • Кто пользователи, сколько их сейчас и через год?
  • Какие 3–5 сценариев критичны? Остальные — вторичны по определению.
  • Что дороже: недоступность или рассогласованность данных? (Ответ определит половину дальнейших решений.)
  • Какой бюджет задержки у ключевого сценария — для пользователя, а не для сервера?
  • Какая доля чтений к записям? Какой профиль нагрузки — ровный, пиковый, сезонный?
  • Что с данными: сколько хранить, можно ли удалять, есть ли требования регуляторов?
  • Какие внешние системы обязательны и какие у них ограничения?
  • Что явно не делаем в этой версии?

Формулировка NFR (non-functional requirements, нефункциональных требований). «Быстро и надёжно» — это не требование. Требование выглядит так:

Доступность API 99.9 % в месяц (≈ 43 мин простоя). p99 ответа на чтение ленты ≤ 300 мс при 5 000 RPS. Потеря подтверждённой записи недопустима (RPO = 0), восстановление после отказа региона ≤ 30 мин (RTO).

Типовые ошибки. Начать с рисования компонентов, не поговорив о требованиях. NFR без чисел. Не зафиксировать «вне рамок» — тогда объём растёт молча.

Готово, когда. Каждое NFR имеет число и способ измерения; требования приоритезированы; есть список исключений.

Связано: OPS-09 SLI, SLO и бюджет ошибок · SEC-11 threat modeling · DATA-19 retention и приватность · PERF-11 стоимость как требование · ARCH-11 офлайн и ненадёжная сеть · Источники: Google SRE Book, гл. 4 «Service Level Objectives», AWS Well-Architected Framework.


W1 · Оценки на салфетке#

Документы шага: нет — шаг идёт по карточкам.

По стадиям.

Стадия Что меняется на этом шаге
гринфилд Все числа — предсказания, и работа не в самих числах, а в проверке на порядок: что изменится, если ошиблись в десять раз. Ошибка на порядок меняет архитектуру, ошибка в полтора раза — нет
работающая Числа берутся из того, что уже меряется, и работа — найти их, а не вывести. Своя ловушка: меряется обычно не то, что нужно шагу

Ловушка общая для обеих стадий, но найдена на гринфилде: шаг считает входные события, а не то, во что событие разворачивается. На прогоне U-02 0,17 подачи в секунду обернулись 933 обращениями к справочникам — событие развернулось в 5 500 раз.

Цель. Понять порядок величин: нужна ли вообще распределённая система, или задача решается одной БД и кэшем.

Выход. Табличка чисел:

  • DAU (активные пользователи за сутки);
  • RPS (запросы в секунду) — средний и пиковый;
  • размер записи;
  • объём данных за год;
  • исходящий трафик;
  • бюджет задержки по компонентам.

Метод. Сверху вниз, в порядках величин, с явными допущениями:

  1. Пользователи → действия на пользователя в день → средний RPS = действия / 86 400.
  2. Пиковый RPS = средний × коэффициент пика (обычно 3–10, для событийных систем — до 100).
  3. Объём = записей в сутки × размер записи × срок хранения × коэффициент репликации/индексов (×2–3).
  4. Трафик = RPS × размер ответа. Часто в деньги упирается он, а не CPU.
  5. Бюджет задержки: разложить целевой p99 по участкам (сеть, API gateway, сервис, БД, сериализация) и проверить, что сумма меньше цели.

Пункты 1–4 считает калькулятор. Он стоит ниже на сайте памятки и в репозитории не работает: GitHub не выполняет скрипты. Кроме самих чисел он показывает то, чего требует стадия гринфилда: меняется ли вывод, если ошиблись в десять раз. А если оставить разворачивание единицей, калькулятор напомнит о нём. Формулы живут здесь, в шаге: разойдётся с ними калькулятор — прав шаг.

Ориентиры для проверки правдоподобия.

  • один узел PostgreSQL уверенно держит тысячи простых транзакций в секунду;
  • один узел Redis — сотни тысяч операций;
  • сеть внутри ЦОД ≈ 0.5 мс, между регионами — десятки миллисекунд;
  • чтение с SSD ≈ 100 мкс, с жёсткого диска ≈ 10 мс.

Типовые ошибки.

  • считать по среднему и не заложить пик;
  • забыть про трафик и его стоимость;
  • считать с точностью до процента там, где неизвестен порядок;
  • не пересчитать после W5.

Готово, когда. Видно узкое место: что упрётся первым — CPU, диск, сеть или деньги.

Связано: PERF-01 числа задержек · PERF-02 перцентили и хвост · PERF-07 закон Литтла и насыщение · OPS-11 ёмкость и автомасштабирование · PERF-08 нагрузочное тестирование · PERF-11 unit-экономика · Источники: Latency Numbers Every Programmer Should Know, Gil Tene, How NOT to Measure Latency.


W2 · Контракты и API#

Документы шага: D-11 гринфилд · работающая

По стадиям. На всех стадиях одинаково.

Цель. Зафиксировать границу между частями системы раньше, чем появится реализация.

Выход. Список операций с сигнатурами, выбранный стиль API, схема данных, модель ошибок, правила идемпотентности, пагинации и версионирования.

Решения этого шага.

  • Синхронно или асинхронно. Если операция может занять больше сотен миллисекунд или зависит от третьей стороны — она асинхронная, и в контракте появляется статус операции.
  • Стиль. REST для ресурсных CRUD-подобных API, gRPC для внутренних вызовов с жёсткими контрактами и стримингом, GraphQL — когда клиентов много и им нужны разные срезы.
  • Push или pull. Нужен ли сервер-инициированный поток: polling, long polling, SSE (server-sent events), WebSocket.
  • Идемпотентность. Любая небезопасная операция, которую клиент может повторить (а он повторит — по таймауту), нуждается в ключе идемпотентности.
  • Ошибки. Различать «повторяй» и «не повторяй»: это контракт для повторов клиента.
  • Совместимость. Как выкатывать клиент и сервер независимо.

Совместимость — это обещание, и у него есть адресат. Как версионировать, описано в NET-17; что мы обещаем и кому — D-11 · Обещание совместимости интерфейса. Обещание там определено как нижняя граница предупреждения, у неё три уровня: «не сузим никогда», «не сузим раньше объявленного срока», «без гарантий». Выбирается оно не вкусом, а тем, что мы знаем о потребителях. Правило оттуда: срок, объявленный тем, кого мы не видим, для потребителя неотличим от отсутствия срока, и записывать его надо честно.

Типовые ошибки.

  • проектировать API от таблиц БД;
  • возвращать 200 с ошибкой в теле;
  • пагинировать по offset растущую коллекцию;
  • оставить без идемпотентности платёжные и «создающие» операции;
  • написать политику совместимости раньше, чем появился список тех, кому её объявлять.

Готово, когда. По контракту можно написать и клиент, и заглушку сервера, не задавая вопросов.

Связано: NET-08 стили API · MSG-01 модели взаимодействия · NET-12 realtime-транспорт · NET-13 асинхронные операции · NET-16 идемпотентность · NET-17 версионирование · NET-18 контракты и схемы · весь блок B01 · Сеть, протоколы, API · Источники: Stripe API — Idempotent Requests, Google API Design Guide, RFC 9110 — HTTP Semantics.


W3 · Данные: модель и хранилище#

Документы шага: D-01 гринфилд · работающая · D-07 гринфилд · работающая · D-08 под изменением

По стадиям.

Стадия Что меняется на этом шаге
гринфилд Копий данных нет ни одной, и вопрос «сколько их уже есть» читается как «сколько мы заведём»: ответ — решение, а не замер. D-08 неприменим: переезжать не от чего. Первичная загрузка справочников — ввод, а не переезд
работающая Копии существуют и считаются. Появляется вторая половина вопроса — как перейти, — и её легко принять за исполнение первой
под изменением Шаг раздваивается: «какой системе быть» (D-07) и «как в неё перейти» (D-08) — разные решения с разными дисквалификаторами и общим окном с D-09. Второе легко не заметить: оно выглядит исполнением первого, а по данным изменение системы ломает её чаще, чем её собственный код

Цель. Выбрать модель и хранилище от того, как данные читают и пишут, а не от привычки.

Выход. Концептуальная модель, список паттернов доступа, выбор хранилищ с обоснованием, ключи и стратегия роста.

Порядок действий.

  1. Выписать сущности и связи.
  2. Выписать паттерны доступа: «получить ленту пользователя за период, 5 000 RPS, p99 200 мс», «найти заказ по номеру», «отчёт за месяц».
  3. Для каждого паттерна — какой индекс или ключ его обслуживает.
  4. Выбрать хранилище: реляционное по умолчанию; отклонение от умолчания требует обоснования (объём, форма данных, профиль нагрузки).
  5. Решить, что будет источником истины, а что — производной проекцией (кэш, поисковый индекс, витрина).

Ключевые развилки. Нормализация против денормализации (стоимость чтения против стоимости согласованности). Один тип хранилища или несколько (polyglot persistence — это ещё и несколько операционных контуров). Разделение OLTP и OLAP (транзакционной и аналитической нагрузки).

Типовые ошибки.

  • выбор БД до формулировки паттернов доступа;
  • аналитика на БД прода;
  • ключ шардирования, выбранный до того, как понятен профиль запросов;
  • хранение файлов в БД.

Готово, когда. Для каждого критичного запроса понятно, какой индекс его закрывает и сколько данных он трогает.

Решения этого шага. D-01 · Выбор хранилища — вопросы, оси, дисквалификаторы, рыночный слой. Шаг говорит, что решить; документ решения — как выбрать и что приложить к ADR (architecture decision record, запись архитектурного решения).

Связано: DATA-01 выбор хранилища · DATA-03 моделирование от паттернов доступа · DATA-05 индексы · DATA-04 типы данных: деньги и время · DATA-02 специализированные хранилища · DATA-15 OLTP и OLAP · DIST-09 генерация уникальных ID · весь блок B03 · Хранилища и данные · Источники: Kleppmann, «Designing Data-Intensive Applications», гл. 2–3, Amazon DynamoDB — Best Practices for Design.


W4 · Верхнеуровневая архитектура#

Документы шага: D-05 гринфилд · D-02 работающая

По стадиям.

Стадия Что меняется на этом шаге
гринфилд Границы закладывают предсказанием: истории изменений нет, измерять связность нечем. Документ шага — D-05. Дешёвое здесь то, что после запуска дорого: стянуть класс защищаемых данных в одну границу ничего не стоит
работающая Границы режут по измерению — связность изменений считается по репозиторию и трекеру. Документ шага — D-02

Единственный шаг, где стадия меняет сам документ, а не его прочтение. Взять не тот — не неточность, а неприменимый метод: раздел 1 D-02 на гринфилде заполнять нечем.

Цель. Собрать компоненты и показать, как проходит запрос.

Выход. Диаграмма компонентов (C4 уровня «контейнеры») + пошаговый проход 2–3 ключевых сценариев: кто кого вызывает, что пишется, что читается.

Правила.

  • Компонент появляется в схеме, только если у него есть зона ответственности одной фразой. «Сервис обработки» — не зона ответственности.
  • Показать поток данных, а не только стрелки: что передаётся и в каком объёме.
  • Отметить синхронные и асинхронные границы разными линиями — это будущие точки отказа.
  • Сразу отметить, где данные дублируются (кэш, индекс, проекция) — это будущие точки рассогласования.

Типовые ошибки. Схема из 15 квадратов без потоков. Микросервисы «на будущее» при одной команде и 100 RPS. Отсутствие ответа на вопрос «что произойдёт, если этот квадрат недоступен».

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

Решения этого шага. Два, по стадии проекта: метод у них разный, а не только числа. Какой когда — сказано в блоке «по стадиям» в начале шага.

Связано: NET-21 устройство веб-приложения · DIST-11 карта паттернов · ARCH-01 монолит и микросервисы · ARCH-02 границы контекстов · ARCH-03 внутренняя архитектура сервиса · ARCH-04 хореография и оркестрация · MSG-02 очередь против лога · EDGE-03 API gateway · весь блок B07 · Архитектурные стили · Источники: C4 model, arc42.


W5 · План масштабирования#

Документы шага: D-03 гринфилд · работающая

По стадиям. На всех стадиях одинаково.

Цель. Понять, что делать, когда нагрузка вырастет в 10 и в 100 раз — и не делать этого заранее.

Порядок применения. Шаги идут строго по очереди:

  1. Измерить — найти реальное узкое место, а не предполагаемое.
  2. Вертикально — увеличить машину. Скучно, но до определённого масштаба дешевле всего.
  3. Кэш — снять чтения, если нагрузка в основном на чтение.
  4. Реплики чтения — если кэш не спасает; сразу принять лаг репликации как факт.
  5. Асинхронность — вынести всё, что не нужно клиенту немедленно, в очередь.
  6. Шардирование — когда один узел не держит записи или объём.
  7. Разделение сервисов — когда причина не в нагрузке, а в организации и цикле релизов.

Типовые ошибки.

  • начать с шардирования;
  • кэшировать то, что не узкое место;
  • считать горизонтальное масштабирование бесплатным: оно переносит стоимость в согласованность и эксплуатацию;
  • не пересчитать оценки W1 после изменений.

Готово, когда. Для каждого узкого места есть следующий шаг и известен признак, по которому его пора делать.

Решения этого шага. D-03 · Стратегия кэширования — короткая форма: умолчание и условия отклонения вместо сравнения вариантов, потому что решение обратимо, а ошибка стоит дней.

Связано: DIST-01 вертикально против горизонтально · CACHE-01 уровни кэша · DATA-09 репликация · DATA-10 шардирование · EDGE-01 балансировка нагрузки · PERF-06 пулы соединений и N+1 · PERF-05 оптимизация API


W6 · Согласованность и корректность#

Документы шага: D-04 гринфилд · работающая

По стадиям. На всех стадиях одинаково.

Цель. Определить, где нужна строгая согласованность, а где допустима отложенная — и как это не сломается при повторах и гонках.

Что решается.

  • Границы транзакций. Что должно меняться атомарно. Всё, что не поместилось в одну транзакцию, становится распределённой операцией.
  • Модель согласованности для каждого чтения: строгая, read-your-writes, causal (причинная), eventual (отложенная). У разных экранов разные требования.
  • Распределённые операции.
    • saga (оркестрация или хореография) с компенсациями;
    • transactional outbox для атомарной записи «в БД + в очередь»;
    • 2PC (two-phase commit, двухфазная фиксация) — только когда участники её поддерживают и вы готовы к блокировкам.
  • Идемпотентность и дедупликация. Повтор должен быть безопасным на всех уровнях: клиент → API → потребитель.
  • Гонки за дефицитным ресурсом (билет, остаток на складе, уникальный ник): оптимистическая блокировка с версией, уникальный индекс, резервирование с TTL.

Типовые ошибки. Считать, что «есть транзакции» = «нет гонок» (read committed допускает write skew — перекос записи). Двойная запись в БД и очередь без outbox. Обещание exactly-once (ровно один раз) там, где его обеспечивает только дедупликация по ключу.

Готово, когда. Для каждой критичной операции описано поведение при повторе, частичном отказе и параллельном выполнении.

Решения этого шага. D-04 · Связь сервисов в рабочем процессе — три двоичных вопроса задают ячейку из восьми; принимается для каждого процесса, пересекающего границы сервисов, отдельно.

Связано: DATA-07 ACID и транзакции · DATA-08 уровни изоляции · DIST-03 модели согласованности · DIST-08 распределённые транзакции и saga · MSG-07 transactional outbox · MSG-06 гарантии доставки · NET-16 идемпотентность · весь блок B06 · Распределённые системы · Источники: Kleppmann, DDIA, гл. 7 и 9, microservices.io — Saga, PostgreSQL — Transaction Isolation.


W7 · Надёжность и деградация#

Документы шага: D-06 гринфилд · работающая

По стадиям. На всех стадиях одинаково.

Цель. Описать поведение системы при отказах — потому что отказ не гипотеза, а расписание.

Инструмент — матрица отказов. Для каждого компонента: что откажет → что увидит пользователь → что делает система → как узнаем.

Отказ Последствие Реакция Обнаружение
Реплика БД недоступна Рост задержки чтений Переключение на другую реплику, чтение с лидера для критичных запросов Алерт по ошибкам пула
Payment gateway (платёжный шлюз) тормозит Очередь запросов, исчерпание пула Таймаут 2 с, circuit breaker, очередь на повтор p99 внешнего вызова
Пропала половина подов Просадка ёмкости Автоскейлинг, ограничение нагрузки Readiness-проба, SLO

Что отключаем и что показываем вместо — решение, а не механика. Механизмы ниже описаны в карточках блока REL и обычно известны команде. Неизвестно другое: что система обещает показать, когда правильный ответ недоступен. Это D-06 · Деградация при отказе и перегрузке, и принимается оно по функции, а не по системе.

Обязательные механики.

  • таймауты на каждом сетевом вызове, без исключений;
  • повторы с exponential backoff и jitter, ограниченные бюджетом;
  • circuit breaker перед нестабильными зависимостями;
  • bulkhead — изоляция пулов, чтобы одна зависимость не съела все потоки;
  • graceful degradation (плавная деградация): что отключаем первым (рекомендации, персонализация) и что защищаем до последнего (оформление заказа).

Уровень выше. Multi-AZ (несколько зон доступности) по умолчанию; multi-region — только если этого требует SLO, потому что цена высокая. Бэкапы, проверенные восстановлением, RPO и RTO как числа.

Типовые ошибки. Повторы без jitter и без бюджета (усиливают сбой). Отсутствие таймаута по умолчанию. Health check, проверяющий процесс, но не зависимости — или наоборот, роняющий живые узлы из-за чужой проблемы.

Готово, когда. Матрица отказов заполнена, у каждой строки есть реакция и способ обнаружения; известны RPO/RTO.

Связано: REL-06 обзор отказоустойчивости · REL-01 таймауты и повторы · REL-02 circuit breaker и bulkhead · REL-03 load shedding · REL-04 деградация и фича-флаги · REL-07 ячеистая архитектура · REL-09 бэкапы, RPO и RTO · DIST-06 обнаружение отказов · весь блок B08 · Надёжность · Источники: Nygard, «Release It!», AWS Builders' Library — Timeouts, retries and backoff with jitter.


W8 · Безопасность#

Документы шага: нет — шаг идёт по карточкам.

По стадиям. На всех стадиях одинаково.

Цель. Закрыть аутентификацию, авторизацию, данные и периметр — до того, как система появится в интернете.

Что описывается.

  • Аутентификация. Сессии или токены; для сторонних клиентов — OAuth 2.0 / OIDC (OpenID Connect). Хранение паролей — только сильный медленный хэш с солью.
  • Авторизация. Модель прав (RBAC / ABAC / ReBAC) и место проверки: в API gateway, в сервисе или в запросе к данным. Проверка «на клиенте» — не проверка.
  • Данные. Что считается персональными данными, что шифруется в покое и в канале, где ключи, как ротируются, что попадает в логи (и что не должно).
  • Периметр. Rate limiting, ограничение размера запроса, валидация ввода, CORS, защита от перебора.
  • Секреты. Хранилище секретов, ротация, отсутствие секретов в репозитории и в переменных окружения образа контейнера.
  • Аудит. Кто, что и когда сделал с чувствительными данными.

Мини-threat model (моделирование угроз). Для каждого входа в систему: кто может обратиться, что подделает, что перехватит, чем перегрузит.

Типовые ошибки.

  • авторизация «по факту наличия токена»;
  • секреты в конфигах;
  • PII (персональные данные) в логах и трассировках;
  • rate limiting только на уровне пользователя, но не на уровне IP или ключа.

Готово, когда. Для каждой роли и каждого ресурса ясно, кто имеет доступ и где это проверяется.

Связано: SEC-01 аутентификация · SEC-04 авторизация · SEC-06 безопасность API · SEC-07 типовые атаки · SEC-08 шифрование и секреты · SEC-09 транспортная безопасность · EDGE-06 rate limiting · SEC-11 threat modeling · весь блок B09 · Безопасность · Источники: OWASP API Security Top 10, RFC 9700 — OAuth 2.0 Security Best Current Practice, NIST SP 800-207 — Zero Trust.


W9 · Observability и эксплуатация#

Документы шага: D-09 гринфилд · работающая

По стадиям.

Стадия Что меняется на этом шаге
гринфилд Наблюдать нечего: трафика нет и не будет до запуска. Шаг превращается из «что мы видим» в «что построить к первому дню», и его результат — список сигналов с ценой, а не отчёт о текущем состоянии. У первой выкатки нет предыдущей версии, и часть вопросов об откате на нём не срабатывает
работающая Сигналы есть; работа — проверить, отвечают ли они на вопрос последнего разбора, и во что обходятся при десятикратном росте
под изменением Добавляется то, чего нет в обоих остальных: две версии работают одновременно, и observability должна различать их. Окно сосуществования — общее с W3 и с D-08

Цель. Сделать систему диагностируемой и выпускаемой.

Observability (наблюдаемость).

  • Метрики. Для сервисов — RED (Rate, Errors, Duration), для ресурсов — USE (Utilization, Saturation, Errors). Следить за перцентилями, не за средним.
  • Логи. Структурированные, с идентификатором запроса, без чувствительных данных.
  • Трассировка. Сквозной trace ID через все сервисы и очереди — иначе распределённый запрос не разобрать.
  • SLI/SLO и бюджет ошибок (error budget). Алерты по симптомам, видимым пользователю, а не по загрузке CPU.

Эксплуатация.

  • стратегия выкатки: rolling, blue-green, canary;
  • фича-флаги;
  • план миграций схемы без простоя: expand → migrate → contract;
  • runbook (инструкция дежурному) на каждый алерт;
  • постмортемы без поиска виноватых.

Стратегия выкатки выбирается однажды, обратимость — на каждое изменение. D-09 · Обратимость выката отвечает на вопрос, который стратегия не задаёт. Сможет ли предыдущая версия работать с состоянием мира после выкатки — со схемой, с сообщениями, уже лежащими в очередях, с кэшами и контрактами? «Откат за секунды» из описания стратегии бывает фикцией, и обнаруживается это в единственный неподходящий момент.

Типовые ошибки.

  • алерт на каждую аномалию — дежурный перестаёт их читать;
  • логи без trace ID;
  • метрики с высокой кардинальностью, роняющие систему мониторинга;
  • миграция схемы, требующая одновременной выкатки кода.

Готово, когда. На вопрос «пользователю плохо — в каком месте?» отвечает дашборд, а не догадка.

Связано: OPS-07 observability · OPS-09 SLI, SLO, бюджет ошибок · OPS-10 алертинг и дежурства · OPS-02 стратегии выкатки · DATA-17 миграции без простоя · OPS-12 тестирование · OPS-03 окружения и тестовые данные · OPS-13 отладка в проде · весь блок B10 · Доставка и эксплуатация · Источники: Google SRE Book, OpenTelemetry docs, Brendan Gregg — USE Method.


W10 · Стоимость и trade-offs#

Документы шага: нет — шаг идёт по карточкам.

По стадиям. На всех стадиях одинаково.

Цель. Показать, что вариант выбран осознанно, а не потому, что первым пришёл в голову.

Выход. Сравнение 2–3 альтернатив по осям: сложность, задержка, согласованность, стоимость, операционная нагрузка, обратимость решения.

Ось Вопрос
Сложность Сколько новых компонентов надо эксплуатировать?
Задержка Что происходит с p99 ключевого сценария?
Согласованность Что пользователь увидит устаревшим и надолго ли?
Стоимость Сколько стоит запрос и сколько — хранение за год?
Операции Кто дежурит и что чинит в 3 часа ночи?
Обратимость Насколько дорого откатить это решение через полгода?

Правило. Необратимые решения (формат хранения, ключ шардирования, публичный контракт) требуют больше анализа, чем обратимые (алгоритм балансировки, размер пула). Обратимые решения принимаются быстро и правятся по данным.

Типовые ошибки. Сравнение только по производительности. Игнорирование операционной стоимости нового компонента. Отсутствие оценки «сколько это будет стоить в деньгах».

Связано: PERF-11 стоимость и TCO · OPS-08 стоимость observability · ARCH-09 serverless: когда выгоден · OPS-05 Kubernetes: чего стоит · ARCH-01 монолит против микросервисов · CASE-13 разборы реальных архитектур · Источники: AWS Well-Architected — Cost Optimization Pillar, ByteByteGo — System Design Was HARD - Until You Knew the Trade-Offs, ByteByteGo — System Design Was HARD - Until You Knew the Trade-Offs, Part 2.


W11 · Design review и ADR#

Документы шага: нет — шаг идёт по карточкам.

По стадиям. На всех стадиях одинаково.

Цель. Проверить дизайн чужими глазами и записать, почему решили так.

Чек-лист ревью#

Требования

  • NFR выражены числами и измеримы
  • Явно записано, что вне рамок
  • Профиль нагрузки: пик, а не среднее

Данные

  • Для каждого критичного запроса известен обслуживающий индекс
  • Определён источник истины для каждой сущности
  • План роста: что делаем при ×10 и ×100
  • Миграции схемы возможны без простоя

Корректность

  • Границы транзакций явные
  • Все небезопасные операции идемпотентны
  • Распределённые операции имеют компенсации
  • Гонки за дефицитным ресурсом разобраны

Отказы

  • Таймаут на каждом внешнем вызове
  • Повторы с jitter и бюджетом
  • Заполнена матрица отказов
  • Известны RPO и RTO, бэкап проверен восстановлением

Эксплуатация

  • SLI/SLO определены, алерты по симптомам
  • Сквозная трассировка
  • Стратегия выкатки и отката

Безопасность

  • Модель авторизации и место проверки
  • Секреты вне кода, PII вне логов
  • Rate limiting на периметре

Стоимость

  • Оценена стоимость запроса и хранения
  • Сравнены альтернативы, компромисс записан

Запись решений#

Форма ADR (architecture decision record) — одна на весь документ и версионируется: decisions/01-adr-template.md. Копия формы здесь была бы вторым источником правды и разошлась бы с первым на первой же правке — ровно та ошибка, от которой ADR и защищает.

Каждый ADR в поле «Метод» указывает документ решения с версией и, если он есть, дату рыночного снимка: decisions/02-versioning.md. Через год это единственный способ понять, что в старом решении нужно перепроверить, а что можно не трогать.

Принятый ADR не редактируется. Пересмотр — новый ADR, отменяющий старый; в старом дописывается только строка статуса и ссылка вперёд.

Решения, принятые по пути, собраны в decisions/: к моменту W11 их обычно три-пять, и ADR пишутся по ним, а не с чистого листа.

Связано: REL-06 обзор отказоустойчивости · DATA-16 целостность и сверка данных · SEC-11 threat modeling · OPS-09 SLO и бюджет ошибок · PERF-11 стоимость · антипаттерны как второй чек-лист · числа и матрицы выбора

Источники: Michael Nygard — Documenting Architecture Decisions, ByteByteGo — System Design Interview – BIGGEST Mistakes to Avoid.