ADR (Architecture Decision Records) concept page. Markdown в репо, фиксирующий context + decision + consequences. Lifecycle Proposed -> Accepted -> Deprecated/Superseded. Tooling: adr-tools, log4brains. Scenarios: writing ADR for Postgres vs Mongo, superseding RabbitMQ -> Kafka, onboarding via log4brains, anti-pattern of decisions in Slack threads.
Через год после того, как принято важное архитектурное решение, никто не помнит почему. Новый человек видит «странный» выбор, «исправляет» его — и ломается то, что решение защищало. ADR (Architecture Decision Record, Michael Nygard, 2011) — простой и дешёвый формат: markdown в репозитории, фиксирующий context + decision + consequences. Это память системы, которой иначе не будет.
ADR — это commit message для архитектурных решений. Один файл = одно решение, immutable после принятия. Если решение пересматривается — новый ADR со ссылкой «Supersedes ADR-0007».
Три ключевых свойства:
grep, ревьюится через PR.Accepted -> Superseded by ADR-NNNN. Сам текст не правится никогда. Иначе теряется historical truth.Канонический формат (Nygard): Status / Context / Decision / Consequences. Consequences — самая важная секция: explicit trade-offs (и Positive, и Negative) защищают от «manager-flavored» ADRs где только плюсы.
Четыре группы вокруг lifecycle:
docs/adr/) — где живут ADR. Видны примеры: ADR-0001 Use Postgres [Accepted], ADR-0002 RabbitMQ [Superseded by 0007], ADR-0007 Switch to Kafka [Accepted, Supersedes 0002], плюс template.md. Стрелка 0002 -> 0007 показывает supersede chain.engineer -> pr-draft (Status: Proposed) -> reviewers -> discussion (PR comments) -> merge (Status: Accepted, immutable). После merge файл становится immutable.log4brains (static site с search/timeline/graph) или просто grep по docs/adr/, за 2 часа понимает 80% архитектурных «почему».adr-tools CLI (adr new, adr supersede), log4brains генератор, CI deploy на GitHub Pages.Отдельная группа Anti-pattern показывает что бывает без ADR: slack-thread -> forgotten (6 months later) -> broken-fix -> incident.
И группа Format comparison напоминает что ADR — это один из трёх форматов: ADR (1-2 страницы, immutable, одно решение) vs RFC (5-30 страниц, evolves, community review) vs Design Doc (3-15 страниц, archived, cross-team alignment).
Engineer выбирает primary store для нового сервиса: Postgres vs MongoDB. Запускает adr new "Use Postgres as primary store" — генерирует 0001-use-postgres.md из template со статусом Proposed. В Context фиксирует: команда SQL-fluent, нужен ACID для денег, объём 10M rows за год. В Decision: Postgres 14 + JSONB. В Consequences Positive: mature, ACID, managed offerings. В Consequences Negative: manual sharding при росте, replication lag для read replicas. PR открывается, 4 approver-а из architecture council ревьюят. В comments всплывают альтернативы (CockroachDB — почему нет?), уточнения (JSONB perf — добавьте GIN index в Consequences), out-of-scope (backup strategy = отдельный ADR). Engineer iterates: добавляет «Cockroach rejected: операционная сложность не оправдана для 10M rows; revisit при 100M». Consensus достигнут, merge — Status переходит в Accepted, файл immutable. Через год новый dev спросит «почему не Mongo?» — читает ADR-0001, видит rationale + что Cockroach был considered, не запускает повторную дискуссию.
Через 18 месяцев scale вырос: throughput hit 80K msg/sec, RabbitMQ упирается на 50K. Хочется открыть ADR-0002 «Event bus = RabbitMQ» и заменить на «Kafka» — СТОП. Editing accepted ADR ломает immutability и разрушает главную ценность ADR — historical record. Правильно: adr supersede 2 -t "Switch event bus from RabbitMQ to Kafka" — atomic создаёт ADR-0007 + обновляет статус ADR-0002. Новый ADR-0007 имеет свой Context (throughput exceeded RabbitMQ ceiling), Decision (migrate to Kafka 3.6 в 3 фазы: dual-publish, dual-read, switch), Consequences (Positive: linear scaling, replay; Negative: operational complexity +++, at-least-once требует idempotency). В ADR-0002 единственное изменение — Status: Accepted -> Superseded by ADR-0007. Это ЕДИНСТВЕННОЕ допустимое изменение accepted ADR. Двунаправленная ссылка: 0002 указывает на 0007, 0007 says «Supersedes 0002». log4brains rebuild рендерит supersede граф визуально. Историческая правда сохранена: «в 2024 RabbitMQ был правильным выбором для 5K/s; в 2026 при 80K/s это уже не так».
Day 3 для нового engineer Maria. Уже знакома с кодом, но не понимает «почему 47 микросервисов? почему Postgres + ClickHouse? почему Kafka?». Открывает adr.company.com — log4brains static site с 47 ADRs за 4 года. Timeline view показывает группы по годам. Search kafka находит ADR-0007 (Switch to Kafka), ADR-0023 (Kafka topic naming), ADR-0031 (Kafka Connect for CDC). Читает ADR-0007, видит «Supersedes ADR-0002» — кликает, попадает в оригинальный rationale RabbitMQ. Инсайт: «RabbitMQ был не ошибкой — это был правильный выбор для 2024 scale. Просто переросли». Graph view рендерит цепочку 0002 -> 0007 -> 0031 — эволюция messaging stack за 4 года стала видна. Search postgres mongo находит ADR-0001 с явным rejection CockroachDB — Maria не пытается reopen ту же дискуссию на standup. Через 2 часа прочитала 30 ADRs, понимает 80% архитектурных «почему». Альтернатива без отдельного site: grep -ri "kafka" docs/adr/ в IDE работает не хуже, потому что ADR — это просто markdown.
Q3 2024: обсуждение в #architecture Slack: «use Mongo для product catalog, schema flexibility важна». 12 сообщений с альтернативами и trade-offs, «ладно, договорились» — но НИКТО не написал ADR. Через 90 дней Slack retention удаляет thread. Q1 2025: новый senior dev Alex смотрит на product catalog: «Why Mongo? У нас Postgres везде, это inconsistency». Решает мигрировать на Postgres «для consistency» — не зная, что Mongo был выбран ИМЕННО за flexibility schema. Переписывает product service, schema fixed: name, price, sku, categories. Через 2 недели product team launches новую категорию мебели с другими атрибутами (габариты, материалы) — schema-rigid Postgres блокирует launch. Эмерженси meeting, выясняется что Mongo был осознанным выбором (200 SKU types, каждый со своими атрибутами), откатывают. Cost: 3 недели работы Alex выкинуты, 2 недели delay для product team, потеря trust между teams. Root cause: не Alex плохой — он действовал rationally based on visible info. Виновата отсутствующая ADR. Стоимость ADR: 30 минут написать в Q3 2024. Saved: 5 weeks engineering + delayed launch.
За:
Против:
ADR vs RFC vs Design Doc — три перекрывающихся формата:
Правило большого пальца: для сложного дизайна пишите Design Doc + потом extract ADRs из ключевых решений. ADR — это distillation, а не полный контекст.
kubernetes/enhancements repo, ADR-like но больше (ближе к RFC по формату).docs/adr/, рендерит timeline + supersede graph.dayjs vs date-fns для одного поля; ADR превратится в шум.adr new, adr supersede, adr link. Минимальный tooling overhead.docs/adr/.