коротко

ADR (Architecture Decision Record) — это короткая запись об одном значимом техническом решении: какой был контекст, что решили, какие были альтернативы и какие последствия. Решает конкретную боль — через полгода никто не помнит, почему выбрали именно так, и команда либо ломает рабочее решение, либо боится его трогать. Формат простой: контекст → решение → статус → последствия. Заводят ADR на решения, которые трудно или дорого откатить: выбор базы, стиля API, способа аутентификации. ADR не заменяет дизайн-документы, а объясняет решения внутри них. Ниже — полный пример одного ADR.

Однажды я полдня выяснял, почему в проекте все суммы хранятся в копейках целым числом, а не в рублях с дробью. Это выглядело странно, кто-то уже хотел «исправить». Я обошёл четверых, и только пятый вспомнил: была история с ошибками округления при расчёте НДС, из-за которой копейки разъезжались, и команда сознательно ушла от дробных чисел. Это решение спасло их от целого класса багов — но нигде не было записано. Ещё чуть-чуть, и кто-то бы его «починил» обратно. После этого я завёл в проекте папку с ADR.

Какую боль решает ADR

Любая система — это слой за слоем принятых решений. Почему очередь, а не прямой вызов? Почему PostgreSQL, а не Mongo? Почему версионирование API через URL, а не через заголовок? Каждое такое решение принималось в каком-то контексте: были ограничения, были альтернативы, был выбор с осознанной ценой. Но контекст испаряется. Люди уходят, детали забываются, и через полгода остаётся только результат без объяснения.

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

ADR фиксирует «почему», а не «как»

ADR — это не инструкция и не дизайн. Он не описывает, как устроена база до последнего индекса — для этого есть HLD и LLD. ADR отвечает на единственный вопрос: «почему мы выбрали именно это, а не очевидную альтернативу?». Если запись не содержит отвергнутых вариантов и их минусов — это не ADR, а просто заметка.

Формат: контекст → решение → статус → последствия

Сила ADR в том, что он крошечный и стандартный. Одна страница, четыре обязательных блока — и его реально пишут, а не откладывают «на потом». Вот что в каждом блоке.

  • Контекст — какая ситуация заставила принимать решение. Какая проблема, какие силы давят (нагрузка, сроки, команда, ограничения). Без эмоций, факты.
  • Решение — что именно решили. Одно предложение по сути плюс пояснение. Формулируется в настоящем: «мы выбираем X».
  • Статус — proposed (предложено), accepted (принято), deprecated (устарело), superseded (заменено другим ADR). Статус живёт и меняется.
  • Последствия — что мы получаем и чем платим. Обязательно и плюсы, и минусы. Если минусов нет — вы их просто не нашли.

Часто добавляют пятый блок — рассмотренные альтернативы: что ещё было на столе и почему отвергли. Это сердце ADR. Решение без альтернатив не объясняет ничего: «выбрали PostgreSQL» бесполезно, а «выбрали PostgreSQL, потому что Mongo не давал нужных нам транзакций при переводах» — объясняет всё.

Статус никогда не редактируют задним числом

Если решение устарело — не удаляйте ADR и не переписывайте его. Заведите новый ADR, а в старом поставьте статус superseded и ссылку на новый. ADR — это журнал, как бухгалтерская книга: записи не стирают, их отменяют новыми. Иначе теряется самое ценное — история того, как менялось мышление команды.

Когда заводить ADR, а когда нет

ADR нужен не на каждый чих. Критерий простой: заводите ADR на решения, которые трудно или дорого откатить и которые затронут многих. Выбор базы данных, стиля API, способа аутентификации, перехода на микросервисы, формата событий в очереди — да. Название переменной, выбор библиотеки для форматирования дат — нет, это легко поменять и это никого не касается.

Хороший триггер: если в обсуждении прозвучала фраза «а давайте обсудим, как лучше» и спор шёл дольше пятнадцати минут — скорее всего, это решение достойно ADR. Раз спорили — значит был неочевидный выбор, и через полгода кто-то заспорит снова, если причина не записана.

Полный пример одного ADR

Вот настоящий ADR — компактный, по формату. Такой можно положить рядом с кодом в папку docs/adr и назвать 0007-postgresql-vs-mongo.md.

ADR-007: Выбор PostgreSQL вместо MongoDB для основного хранилища

Дата:   2026-04-12
Статус: accepted
Автор:  Н. Миронов (аналитик), А. Петров (тимлид)

── КОНТЕКСТ ──────────────────────────────────────
Строим сервис платежей. Нужно надёжно хранить счета,
транзакции и балансы. Ключевое: перевод между счетами
должен списывать с одного и зачислять на другой
атомарно — либо оба, либо ни одного. Команда из 4
бэкендеров, опыт есть и в SQL, и в Mongo. Объём данных
средний (миллионы записей), не big data.

── РАССМОТРЕННЫЕ АЛЬТЕРНАТИВЫ ─────────────────────
1. MongoDB
   + Гибкая схема, быстрый старт, привычна двоим в команде.
   - Многодокументные транзакции есть, но дают слабые
     гарантии под нагрузкой и сложнее в эксплуатации.
   - Денежные операции на схемалесс-базе — риск рассинхрона
     баланса при сбое посреди перевода.
2. PostgreSQL
   + Строгие ACID-транзакции «из коробки» — атомарный перевод
     решается одним BEGIN/COMMIT.
   + Жёсткая схема защищает целостность денежных данных.
   - Менее гибок при частой смене структуры данных.
   - Двое в команде знают его хуже Mongo.
3. PostgreSQL + Mongo (полиглот)
   - Две базы = вдвое больше эксплуатации и точек отказа.
     Для текущего масштаба не оправдано.

── РЕШЕНИЕ ───────────────────────────────────────
Используем PostgreSQL как единственное основное хранилище.
Решающий фактор — атомарность денежных переводов: цена
ошибки (разъехавшийся баланс) выше, чем удобство гибкой
схемы Mongo.

── ПОСЛЕДСТВИЯ ───────────────────────────────────
+ Переводы реализуются простой транзакцией, без ручной
  компенсации при сбоях.
+ Целостность данных гарантирована схемой и ограничениями.
- Изменения структуры данных потребуют миграций — заложили
  инструмент миграций в стек.
- Двоим в команде нужно подтянуть PostgreSQL; запланировали
  внутренний воркшоп на спринт.
- Если в будущем появится подсистема с гибкой схемой
  (например, лог событий) — пересмотрим отдельным ADR.

Разберём, почему это работает. Блок «контекст» называет силу, которая всё решила — атомарность переводов, — а не общие слова «нам нужна надёжная база». Альтернативы поданы честно: у PostgreSQL прямо записан минус «двое знают хуже». Решение в одну фразу с явной ценой выбора. А последствия — это не реклама, там есть и плюсы, и минусы, и даже план, что делать с минусами (воркшоп, инструмент миграций). Через год новый человек прочитает это за две минуты и не полезет «улучшать» базу на Mongo.

Откуда это взялось

Формат ADR придумал и описал Майкл Найгард в 2011 году в заметке «Documenting Architecture Decisions». Его боль была ровно той же, что у всех: проектные решения принимаются, контекст забывается, а толстую архитектурную документацию никто не пишет и не читает. Найгард предложил противоядие — крошечные записи в текстовом виде, по одной на решение, прямо в репозитории рядом с кодом, под версионным контролем. Лёгкость и была идеей: чем меньше церемоний, тем выше шанс, что их реально ведут. С тех пор подход оброс шаблонами (популярен MADR — Markdown ADR), но суть Найгарда не изменилась: контекст, решение, последствия — и ничего лишнего.

Как это спрашивают на собесе

«Что такое ADR и зачем он нужен?» — проверяют, понимаете ли вы боль (потеря контекста решений), а не просто знаете расшифровку аббревиатуры. «Чем ADR отличается от технической документации?» — ждут ответ про «почему против как»: ADR объясняет выбор, дизайн-доки описывают устройство. «Что делать, если решение из старого ADR устарело?» — здесь топят тех, кто говорит «отредактировать»; правильный ответ — завести новый ADR и пометить старый как superseded, не стирая историю.

Частые вопросы

Кто пишет ADR — аналитик или разработчик?

Тот, кто участвует в решении, — а это часто и аналитик, и тимлид вместе. Аналитик особенно полезен в блоке «контекст»: именно он держит бизнес-причины и ограничения, из-за которых решение вообще принимается. Технические альтернативы и последствия обычно формулирует тимлид или архитектор. На практике ADR часто пишут в четыре руки: аналитик описывает «зачем и в каких рамках», инженер — «что выбрали и чем платим».

Где хранить ADR?

Лучше всего — в самом репозитории кода, в папке docs/adr, по одному markdown-файлу на решение с нумерацией (0007-postgresql-vs-mongo.md). Тогда ADR версионируется вместе с кодом, виден в pull request и не отстаёт от реальности. Хранить в вики или Confluence можно, но там записи быстрее протухают и отрываются от кода. Главное — чтобы их легко было найти и чтобы порог завести новый был минимальным.

Чем ADR отличается от HLD/LLD?

HLD и LLD описывают, как система устроена: компоненты, схемы таблиц, контракты. ADR объясняет, почему она устроена именно так: какой выбор сделали на развилке и почему отвергли альтернативу. Они дополняют друг друга — в дизайн-документе можно поставить ссылку на ADR там, где решение неочевидно. Грубо: LLD говорит «таблица accounts с такими-то полями», а ADR рядом говорит «и почему вообще PostgreSQL, а не Mongo».