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 на старте — архитектура на старте.
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 в спринте
- На refinement или архитектурной встрече — тема "нужен ADR".
- Автор — черновик Proposed, ссылка в тикете.
- PR с ADR; обсуждение в комментариях (как к коду).
- Accepted после merge; тикеты на реализацию ссылаются на номер.
- При смене подхода — новый ADR, старый Superseded.
Spike на 1–2 дня часто предшествует ADR: сначала проверили гипотезу, потом зафиксировали решение.
Связь с инцидентами и изменениями
Postmortem после инцидента может показать: архитектурное допущение из ADR-0004 больше не верно. Тогда новый ADR или статус Superseded — не "устное мы передумали". Крупное изменение scope из change request с архитектурным влиянием — повод для ADR до начала разработки.
Минимальный набор ADR на старте проекта
Для старта проекта часто хватает трёх–пяти записей:
- Выбор стека и репозиторной структуры (монорепо / мультирепо).
- СУБД и стратегия миграций.
- Аутентификация и авторизация.
- Стиль интеграций (sync/async).
- Среды (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-диаграммы
| Уровень C4 | ADR |
|---|---|
| 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 новичком — порядок
- Оглавление
docs/adr/README.md— статусы Accepted. - ADR по своему сервису (БД, очередь, auth).
- ADR с пометкой Superseded — понять эволюцию.
- Proposed — можно комментировать в PR.
15–30 минут — достаточно, чтобы не спорить о Redis на первой неделе.
Инструменты
| Инструмент | Назначение |
|---|---|
| adr-tools | CLI: new, generate toc |
| Git + PR | Review и история |
| Docusaurus | Публикация adr как docs |
Шаблон в .github/pull_request_template.md | Поле "ADR-NNN" |
ADR при аудите и сертификации
Аудиторы ИБ и госэксперты спрашивают обоснование технических решений. ADR с датой Accepted и подписью review — доказательство осознанного выбора (шифрование, хранение логов, граница сети). Не заменяет формальный акт, но ускоряет ответы.
Примеры номеров ADR в живом каталоге
| Номер | Тема | Статус |
|---|---|---|
| 0001 | PostgreSQL как основная СУБД | Accepted |
| 0002 | REST для внешнего API | Accepted |
| 0003 | JWT для mobile, cookie для web | Accepted |
| 0004 | Kafka для событий заказов | Superseded by 0012 |
| 0012 | RabbitMQ вместо Kafka (команда 6 чел.) | Accepted |
| 0013 | ЕСИА через OIDC | Proposed |
Новичок читает 0001, 0003, 0012 — понимает 80% споров первого месяца.
Вопросы на архитектурном review ADR
- Что сломается при отказе компонента из решения?
- Как откатимся в первые 24 часа после внедрения?
- Кто on-call по новой зависимости?
- Соответствует ли NFR?
- Нужно ли обучение команды?
- Есть ли план миграции с текущего состояния?
Ответы — в ADR или явно "вынесено в тикет XXX".