Каждая развилка из этого раздела заканчивается решением: взяли ClickHouse, остались на PG FTS, выбрали события вместо REST. Через год приходит новый разработчик — или вы сами — и спрашивает: «почему здесь так?» Если ответ живёт в голове уволившегося и в закрытом треде мессенджера — решение будут пересматривать заново, с теми же спорами и теми же граблями.
ADR (Architecture Decision Record) — короткий документ, фиксирующий одно архитектурное решение: что решили, в каком контексте и чем заплатим. Не проектная документация, не описание системы — именно решение.
Формат
Минимальный рабочий формат — четыре секции (это ядро и классического шаблона Майкла Найгарда, и MADR):
# ADR-007: События в ClickHouse через Kafka-консьюмер, не Kafka-движок
Статус: accepted (2026-06-06)
Заменяет: —
## Контекст
Аналитика заказов переезжает в ClickHouse (ADR-005). События уже идут
через outbox в Kafka. Нужно выбрать способ доставки Kafka → ClickHouse:
Java-консьюмер в сервисе, Kafka-движок ClickHouse или Debezium-пайплайн.
## Решение
Батчевый Java-консьюмер в сервисе заказов.
## Альтернативы
- Kafka-движок ClickHouse: нет Java-кода, но ретраи, маппинг и алерты
уезжают в DDL, который команда сервиса не видит и не ревьюит.
- Debezium CDC: зеркалит строки, а нам нужны доменные события.
## Последствия
+ Маппинг и ретраи в кодовой базе сервиса, под обычным ревью и тестами.
+ Идемпотентность контролируем сами (ReplacingMergeTree по event_id).
− Консьюмер — ещё один компонент сервиса: deployment, мониторинг lag.
− При смене схемы события правим и консьюмер, и таблицу.
Принципиальны две вещи. Контекст — без него решение нечитаемо: «взяли консьюмер» бессмысленно, «взяли консьюмер, потому что владение пайплайном должно остаться у команды сервиса» — знание. Последствия с минусами — ADR без минусов это маркетинг; честные «чем платим» избавляют будущего читателя от иллюзии, что решение бесплатное.
Жизненный цикл
- Статусы:
proposed→accepted→ (superseded by ADR-NNN|deprecated). ADR не редактируют задним числом: решение изменилось — пишется новый, старый получаетsupersededи ссылку. История споров остаётся читаемой. - Нумерация сквозная и навсегда:
ADR-007не переиспользуется, даже если решение отменено. - Хранение — в репозитории, рядом с кодом, который решение описывает:
docs/adr/ADR-007-clickhouse-pipeline.md. Решения платформенного уровня (границы сервисов, общие контракты) — в архитектурном репо рядом с context map. В вики ADR умирают: их не ревьюят с кодом и не находят при чтении репозитория. - Ревью — тем же PR-процессом, что и код.
proposed-ADR в PR — лучший способ обсудить развилку до того, как написаны тысячи строк.
Когда писать — и когда нет
Писать, когда решение дорого отменить и неочевидно без контекста: выбор хранилища, способа интеграции, формата событий, стратегии миграции, отказ от чего-то ожидаемого («не используем JPA», «не версионируем этот API»). Хорошая эвристика: если на ревью или в чате возник спор длиннее десяти сообщений — итог спора стоит ADR.
Не писать: на решения, продиктованные стандартом команды (для этого есть style guide — он сам по себе «большой ADR»), на обратимые мелочи (имя пакета, библиотека-утилита), на то, что очевидно из кода. ADR на каждый чих девальвирует жанр — их перестают читать.
Типичные ошибки
- ADR постфактум-археология. Через год решили «задокументировать всё, что есть» и написали двадцать ADR по памяти. Контекст уже утерян, получились описания, не решения. ADR пишется в момент выбора.
- ADR без альтернатив. «Решили взять X» — а что отвергли и почему? Без отвергнутых вариантов следующий спорщик принесёт их снова.
- Правка вместо superseded. Тихо переписали ADR-003 под новое решение — история умерла, ссылки на старое врут.
- ADR как простыня. Десять страниц с диаграммами — это design doc, не ADR. Решение должно читаться за пару минут; детали — по ссылкам.
- Решение есть, ADR «потом». «Потом» не наступает. ADR входит в definition of done той задачи, где развилка решилась.
ADR и UCP-спека
Это разные жанры, и они не заменяют друг друга: спека описывает, что система делает (use cases, инварианты, события) и обновляется при каждом изменении поведения; ADR фиксирует, почему она так устроена, и не меняется никогда. Спека — живая карта, ADR — журнал свернувших развилок. Платформенные решения дополнительно отражаются в context map архитектурного репозитория — но первоисточник «почему» всегда ADR.
Что почитать дальше
- Монолит или микросервисы, PG vs ClickHouse, sync vs async — развилки, итоги которых стоят ADR.
- Что делает архитектор — чья обязанность довести развилку до записанного решения.
- Модель C4 — диаграммы описывают структуру, ADR — причины; работают в паре.
- Use Case спецификация — «что делает система», парный жанр к «почему так».