Перейти к основному содержимому

ADR — запись архитектурных решений

Архитектору Разработчику

Почему без ADR теряется память проекта

Через год новый разработчик спросит: "Почему PostgreSQL, а не MongoDB?" или "Зачем синхронный REST, а не очередь?" Если ответ только в голове ушедшего сотрудника или в закрытом PR трёхлетней давности — команда переоткрывает тот же спор, тратит недели и иногда принимает противоположное решение без понимания последствий.

ADR (Architectural Decision Record) — короткий текстовый документ о важном архитектурном решении: что выбрали, в каком контексте, какие плюсы и минусы приняли, какие варианты отвергли. Идея популяризована Michael Nygard; в зрелых командах ADR живут рядом с кодом в Git и проходят review как docs-as-code.

Одна фраза

ADR — не энциклопедия архитектуры, а журнал ключевых развилок: контекст, решение, последствия, статус. Один ADR — одна значимая тема.

Связанные разделы: проектирование и архитектура, базы знаний, старт проекта.


Что такое ADR простыми словами

ЭлементСмысл
КонтекстКакая проблема, ограничения, NFR, команда, срок
РешениеЧто выбрали (одним абзацем или списком)
ПоследствияПлюсы, минусы, риски, что придётся делать дальше
СтатусProposed, Accepted, Deprecated, Superseded
СвязиPR, тикеты, другие ADR

ADR не заменяет C4-диаграммы, OpenAPI и runbook — он объясняет почему архитектура выглядит так, а не только как.


Когда писать ADR

Стоит зафиксироватьМожно обойтись без ADR
Выбор СУБД, брокера сообщений, облакаПереименование пакета
Монолит или сервисы, границы bounded contextМелкий локальный рефакторинг
Стратегия аутентификации (OAuth2, SSO, ЕСИА)Форматирование по линтеру
Стиль API (REST, события, gRPC)Один эндпоинт без влияния на систему
Хранение сессий, кэш, мультирегионСмена версии библиотеки без смены подхода
Интеграция с госшиной, СМЭВ, ЕБСПравка текста на кнопке

Правило для новичка: если решение дорого отменить (месяцы работы) или о нём регулярно спрашивают — оформите ADR. Если сомневаетесь — лучше короткий ADR в статусе Proposed, чем спор на каждом онбординге.


Шаблон Michael Nygard

Минимальный шаблон, с которого начинают большинство команд:

# ADR-0007: Хранение сессий в Redis

## Статус
Принято (2024-03-12)

## Контекст
Горизонтальное масштабирование API; sticky sessions на балансировщике нежелательны.
Ожидаемая нагрузка — 5k RPS, три инстанса API за балансировщиком.

## Решение
Сессии в Redis с TTL 24 часа; JWT только для stateless mobile API.

## Последствия
+ Масштабирование без привязки клиента к одному инстансу
+ Единая точка инвалидации сессии при logout
- Зависимость от Redis; нужен мониторинг кластера и план при падении Redis
- Дополнительная задержка 1–2 мс на чтение сессии

Поля Контекст и Последствия — самые важные: они объясняют почему, а не только что. Рекомендуется добавить:

  • Рассмотренные варианты — sticky sessions, JWT в cookie, in-memory;
  • Ссылки — тикет, PR, NFR;
  • Авторы и ревьюеры — кто консультировался (SA, PO).

Расширенный шаблон для команды

# ADR-0012: Очередь заказов на RabbitMQ

## Статус
Принято (2025-01-08)

## Контекст
Пиковая нагрузка на создание заказов; синхронная цепочка из 4 сервисов даёт p95 > 3 с.
NFR: p95 < 800 мс на приём заказа, at-least-once доставка допустима.

## Рассмотренные варианты
1. Kafka — высокая пропускная способность, сложнее эксплуатация для команды из 6 человек.
2. RabbitMQ — уже в [стеке компании], достаточный throughput.
3. PostgreSQL LISTEN/NOTIFY — без отдельного брокера, риск нагрузки на БД.

## Решение
RabbitMQ, отдельная очередь на тип заказа, идемпотентные consumer по id заказа.

## Последствия
+ Быстрый ответ API; обработка асинхронно
+ Повторная доставка без двойного списания при idempotency key
- Нужны DLQ, мониторинг lag, runbook при заторе
- Связано с ADR-0009 (идемпотентность платежей)

## Ссылки
- JIRA-4521, PR #891

Статусы ADR

СтатусСмыслДействие команды
ProposedНа обсуждении, ещё не действуетКомментарии в PR, можно менять
AcceptedДействующее решениеНовый код должен соответствовать
DeprecatedБольше не применяем к новому кодуСтарый код могут трогать по плану миграции
Superseded by ADR-NNNЗаменено другим ADRЧитать новый ADR, старый — для истории

Устаревшие ADR не удаляют — по ним видна эволюция системы при работе с легаси. Удаление "чтобы не путать" — типичная ошибка: через год никто не вспомнит, почему отказались от первого варианта.


Где хранить ADR

Рекомендуется docs-as-code — документация в том же Git, что и код:

  • каталог docs/adr/ или adr/ в корне репозитория;
  • нумерация 0001, 0002 … — порядок принятия, не важности;
  • файл README.md или index.md — оглавление со статусами;
  • изменения через Pull Request и code review;
  • автоматизация — adr-tools (adr new, adr generate toc).

Подробнее — ADR и docs-as-code. Первые ADR на старте — архитектура на старте.

Wiki или Git

Confluence без связи с PR устаревает. ADR в Git версионируются вместе с кодом: видно, какое решение действовало на момент релиза. Краткие выжимки можно дублировать в wiki со ссылкой на файл в репозитории.


Кто пишет и кто ревьюит

РольУчастие
Архитектор / SAИнициирует, черновик контекста и вариантов
ТимлидFeasibility, влияние на команду и сроки
РазработчикиReview в PR — последствия для кода
PO/PMКонсультант, если решение влияет на срок roadmap
DevOps / SREЭксплуатация, мониторинг, on-call
БезопасностьAuth, ПДн, госсегмент

ADR — не монолог архитектора. Один Approved без review — слабый ADR.


Примеры по контекстам

Продуктовая SaaS-компания

ADR-0003: мультитенантность через tenant_id в одной БД, а не отдельная БД на клиента — команда из 8 человек, 200 клиентов, изоляция на уровне row-level security. Последствие: проще деплой; риск — ошибка в запросе без фильтра tenant. Ссылка на ADR-0011 (тесты на утечку tenant).

Аутсорс для банка

ADR передано заказчику в репозитории исполнителя; после сдачи — копия в Git заказчика. В договоре зафиксировано: архитектурные решения уровня СУБД и интеграций — с согласованием архитектора заказчика. Статус Proposed до письма "согласовано".

Госсектор

ADR дополняет ТЗ и протоколы: "почему реляционная БД в контуре X", "почему интеграция через СМЭВ, а не прямой API". На госэкспертизу часто нужны формальные документы; ADR ускоряет ответы экспертам и онбординг подрядчиков смены.


ADR и другие артефакты

АртефактСвязь с ADR
C4 / диаграммыПоказывают структуру; ADR — мотивацию
OpenAPI / контрактыРеализация решения из ADR по API
Техническое письмоФормальный документ для заказчика
RunbookОперационные шаги по последствиям ADR (Redis down)
PostmortemМожет породить новый ADR или Superseded

В PR, меняющем архитектуру, укажите: Relates to ADR-0007 или создайте ADR в том же PR.


Типичные ошибки

ОшибкаПочему плохоЧто делать
ADR на 40 страницНикто не читает1–2 экрана; детали — в коде и wiki
Нет отвергнутых вариантовСпор повторяетсяСекция "Рассмотренные варианты"
Нет последствийНеожиданный техдолгМинусы честно, плюс action items
ADR в Confluence без GitУстарелоdocs-as-code
Удалили старый ADRПотеря историиDeprecated / Superseded
Accepted без reviewРешение одного человекаPR + ревьюеры

Жизненный цикл ADR в спринте

  1. На refinement или архитектурной встрече — тема "нужен ADR".
  2. Автор — черновик Proposed, ссылка в тикете.
  3. PR с ADR; обсуждение в комментариях (как к коду).
  4. Accepted после merge; тикеты на реализацию ссылаются на номер.
  5. При смене подхода — новый ADR, старый Superseded.

Spike на 1–2 дня часто предшествует ADR: сначала проверили гипотезу, потом зафиксировали решение.


Связь с инцидентами и изменениями

Postmortem после инцидента может показать: архитектурное допущение из ADR-0004 больше не верно. Тогда новый ADR или статус Superseded — не "устное мы передумали". Крупное изменение scope из change request с архитектурным влиянием — повод для ADR до начала разработки.


Минимальный набор ADR на старте проекта

Для старта проекта часто хватает трёх–пяти записей:

  1. Выбор стека и репозиторной структуры (монорепо / мультирепо).
  2. СУБД и стратегия миграций.
  3. Аутентификация и авторизация.
  4. Стиль интеграций (sync/async).
  5. Среды (dev/stage/prod) и секреты.

Не обязательно всё Accepted в день один — Proposed с датой review тоже ценность.


Нумерация и именование файлов

Распространённые соглашения:

  • docs/adr/0001-use-postgresql.md — номер в имени файла;
  • заголовок внутри: # 1. Use PostgreSQL или # ADR-0001: PostgreSQL;
  • не переиспользовать номер удалённого ADR;
  • дата в статусе — дата принятия, не черновика.

adr-tools создаёт следующий номер автоматически — меньше конфликтов в PR.


Review ADR в Pull Request

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

  • Понятен контекст без знания тайны проекта?
  • Есть минимум два рассмотренных варианта?
  • Последствия включают минусы и операционные затраты?
  • Статус корректен (не Accepted до согласования)?
  • Ссылки на тикеты/PR, где решение внедряется?
  • NFR из требований упомянуты, если релевантны?

Комментарий "не нравится" без альтернативы — слабый review. Лучше: "вариант B с managed Kafka — сравнить стоимость в ADR".


ADR и C4-диаграммы

Уровень C4ADR
System contextРоль системы в ландшафте (иногда ADR на границу)
ContainerЧасто — выбор БД, API gateway, брокер
ComponentРеже — только спорные модули
CodeПочти никогда — это код и тесты

Диаграмма без ADR отвечает "как выглядит"; ADR — "почему так, а не иначе". Обе устаревают — ADR проще diff в Git.


MADR и другие форматы

Существуют варианты шаблона (MADR — Markdown ADR с полями Decision Drivers). Суть та же: контекст, решение, последствия. Команда выбирает один шаблон и не спорит о формате вместо содержания. В wiki — ссылка на шаблон в репо.


ADR в микросервисах и монорепо

СтруктураГде ADR
МонорепоОдин каталог docs/adr/ на весь продукт
МультирепоADR в репо владельца сервиса; кросс-сервисные — в platform-репо
Платформа + продуктыPlatform ADR (Kafka) + product ADR (использование топиков)

Кросс-сервисный ADR без владельца — никто не обновляет при смене контракта.


Пример ADR для аутсорса (интеграция 1С)

Заказчик требует обмен с 1С. ADR-0004 (статус Proposed до согласования):

  • Контекст — 50k номенклатур, обновление раз в час, on-prem 1С заказчика.
  • Варианты — прямой OData; файловый обмен на SFTP; message bus.
  • Решение — SFTP + идемпотентный импорт по batch id (проще для ИБ заказчика).
  • Последствия — lag до 1 ч; runbook при битом файле; не real-time.

Архитектор заказчика комментирует в PR — после письма "согласовано" статус Accepted.


ADR после легаси-аудита

При легаси команда пишет ретроспективные ADR: "как есть сейчас" со статусом Accepted и пометкой as-is legacy. Это останавливает мифы. Новые ADR — Superseded по мере рефакторинга (Strangler и т.д.).


Ритуалы команды

  • Архитектурный час раз в две недели — Proposed ADR на обсуждение.
  • Онбординг — прочитать 3 последних Accepted ADR по своему сервису.
  • Postmortem — пункт "нужен ли новый ADR?"
  • Release notes для внутренних команд — ссылка на ADR при ломающих изменениях.

Связь с PO и сроками

ADR на месяц разработки влияет на roadmap — PO консультируется (C в RACI), но не пишет ADR. Если ADR откладывает фичу на квартал (например, миграция БД) — PO пересматривает backlog и CR к заказчику.


ADR, RFC и design doc — не путать

АртефактНазначениеЖизненный цикл
ADRОдно архитектурное решениеСтатусы, короткий текст
RFCПредложение на широкое обсуждениеDraft → comment → accept
Design docПлан реализации крупной фичиВременный, до релиза
ТЗ / техписьмоФормальный договор с заказчикомВерсии, экспертиза

Внутри команды ADR; перед крупной фичей на квартал — design doc со ссылками на ADR. В аутсорсе заказчику — техписьмо, внутри — ADR.


Чтение ADR новичком — порядок

  1. Оглавление docs/adr/README.md — статусы Accepted.
  2. ADR по своему сервису (БД, очередь, auth).
  3. ADR с пометкой Superseded — понять эволюцию.
  4. Proposed — можно комментировать в PR.

15–30 минут — достаточно, чтобы не спорить о Redis на первой неделе.


Инструменты

ИнструментНазначение
adr-toolsCLI: new, generate toc
Git + PRReview и история
DocusaurusПубликация adr как docs
Шаблон в .github/pull_request_template.mdПоле "ADR-NNN"

ADR при аудите и сертификации

Аудиторы ИБ и госэксперты спрашивают обоснование технических решений. ADR с датой Accepted и подписью review — доказательство осознанного выбора (шифрование, хранение логов, граница сети). Не заменяет формальный акт, но ускоряет ответы.


Примеры номеров ADR в живом каталоге

НомерТемаСтатус
0001PostgreSQL как основная СУБДAccepted
0002REST для внешнего APIAccepted
0003JWT для mobile, cookie для webAccepted
0004Kafka для событий заказовSuperseded by 0012
0012RabbitMQ вместо Kafka (команда 6 чел.)Accepted
0013ЕСИА через OIDCProposed

Новичок читает 0001, 0003, 0012 — понимает 80% споров первого месяца.


Вопросы на архитектурном review ADR

  1. Что сломается при отказе компонента из решения?
  2. Как откатимся в первые 24 часа после внедрения?
  3. Кто on-call по новой зависимости?
  4. Соответствует ли NFR?
  5. Нужно ли обучение команды?
  6. Есть ли план миграции с текущего состояния?

Ответы — в ADR или явно "вынесено в тикет XXX".


Итоги и чек-лист

Итоги раздела · Чек-лист