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».