# Software Architect: мышление, язык и практика

Полный курс для опытного инженера, который хочет думать и говорить как архитектор: trade-offs, границы, данные, распределённые системы, качество, коммуникация и AI-native работа. 52 понятия — у каждого английский термин, схема и карточка «что это → пример → цена → связи»; в конце — шпаргалка по всем понятиям.

- **Author:** Фёдор Чищин
- **Level:** advanced
- **Reading time:** ~7 часов чтения
- **Published:** 2026-05-23
- **Source:** https://fedorthinks.com/ru/learn/software-architect

---

#### Подробные модули

- [01. Кто такой архитектор](./software-architect-01-role)
- [02. Trade-offs](./software-architect-02-tradeoffs)
- [03. Технический долг](./software-architect-03-technical-debt)
- [04. Cognitive load](./software-architect-04-cognitive-load)
- [05. Декомпозиция](./software-architect-05-decomposition)
- [06. Слои и зависимости](./software-architect-06-layers)
- [07. API и контракты](./software-architect-07-api-contracts)
- [08. Модель данных](./software-architect-08-data-model)
- [09. Состояние](./software-architect-09-state)
- [10. Распределённые системы](./software-architect-10-distributed-systems)
- [11. Монолит и микросервисы](./software-architect-11-monolith-microservices)
- [12. Sync и async](./software-architect-12-sync-async)
- [13. Производительность](./software-architect-13-performance)
- [14. Масштабируемость](./software-architect-14-scalability)
- [15. Надёжность](./software-architect-15-reliability)
- [16. Безопасность](./software-architect-16-security)
- [17. Наблюдаемость](./software-architect-17-observability)
- [18. Документация](./software-architect-18-documentation)
- [19. Коммуникация](./software-architect-19-communication)
- [20. Лидерство без власти](./software-architect-20-leadership)
- [21. Бизнес и продукт](./software-architect-21-business-product)
- [22. AI-native архитектор](./software-architect-22-ai-native)
- [23. Антипаттерны](./software-architect-23-antipatterns)
- [24. Постоянный рост](./software-architect-24-growth)

## 1. Кто такой архитектор

Архитектор отличается от senior-инженера не тем, что знает больше технологий. Он отвечает за последствия решений во времени.

### Course map — 24 модуля в шести частях

> Карта метро: сначала видишь все линии целиком, потом едешь по станциям.

Курс идёт от мышления к практике. Сначала — как думает архитектор (**mindset**). Потом — как устроена система внутри (**structure**) и что меняется, когда она расползается по сети (**distribution**). Дальше — свойства качества (**quality attributes**), работа с людьми (**people**) и то, куда профессия движется (**future**).

_Diagram: 24 модуля курса в шести частях: мышление → структура → распределённость → качество → люди → будущее._

Как читать: у каждого понятия есть **английский термин** (его ищут в документации и слышат на собеседованиях), образ из жизни, **схема** и **карточка** с полями «что это / пример / цена / связи». В конце курса — шпаргалка по всем понятиям на одной странице.

### Long-term thinking — архитектор думает горизонтом лет

> Инженер строит мост, по которому завтра проедет машина. Архитектор спрашивает, что будет, когда по нему начнут ездить грузовики, когда рядом построят новый район и когда ремонт станет дороже самого моста.

Инженер чаще всего решает задачу **как она поставлена**. Архитектор сначала проверяет, правильно ли поставлена задача. Это не снобизм и не желание «поговорить о высоком». Просто архитектурное решение обычно дороже изменить, чем строку кода.

Главный сдвиг в голове: ты перестаёшь спрашивать только «как сделать X» и начинаешь спрашивать **«зачем нужен X, какие есть альтернативы, что мы потеряем и как это решение будет выглядеть через три года»**.

_Diagram: Инженер смотрит на задачу «как она поставлена». Архитектор растягивает тот же вопрос на годы вперёд._

#### Long-term Thinking (мышление горизонтом лет)

- **Что это:** Оценивать решение не только по «работает завтра», но и по тому, как оно поведёт себя через год-три.
- **Как работает:** Перед «как сделать X» — «зачем X», какие альтернативы, что потеряем.
- **Пример:** Мост: выдержит ли он грузовики, новый район рядом и ремонт дороже самого моста.
- **Подвох:** Это не повод проектировать «на вырост» — только вопрос, который надо задать.
- **Связи:** **Reversible decisions**, **trade-offs**, **technical debt**.

### Reversible vs irreversible decisions — отвечать за форму системы

> Если плотник ошибся с полкой, её можно перевесить. Если проектировщик ошибся с несущей стеной, дом будет жить с этой ошибкой десятилетиями.

Архитектор не обязан лично принимать каждое техническое решение. Но он обязан владеть решениями, которые задают форму системы: границы сервисов, модель данных, протоколы интеграции, стратегия масштабирования, безопасность, наблюдаемость, путь миграции.

Здесь полезно различать **reversible decisions** и **irreversible decisions**. Обратимое решение можно поменять за день или неделю: библиотека логирования, цвет кнопки, мелкая внутренняя структура модуля. Необратимое или дорого обратимое решение меняет траекторию системы: база данных, модель tenancy, API-контракт, способ хранения событий, границы сервисов.

_Diagram: Обратимые решения принимай быстро. Необратимые задают форму системы — ими владеет архитектор._

#### Reversible vs Irreversible (обратимые и необратимые решения)

- **Что это:** Разделение решений по цене отката: дни-недели против месяцев-лет.
- **Как работает:** Обратимые решаем быстро и не спорим долго; необратимые — медленно, с альтернативами и записью.
- **Пример:** Библиотека логирования — обратимо. Модель tenancy или API-контракт — почти нет.
- **Подвох:** Тратить неделю обсуждений на обратимую мелочь — так же плохо, как решить необратимое за час.
- **Связи:** **Data model**, **API contract**, **service boundaries**.

> **Главный вопрос:** Если это решение окажется неверным через год, сколько людей и сколько систем будут за него платить?

#### Вопросы архитектора

- Какую проблему мы решаем на самом деле?
- Что изменится, если нагрузка вырастет в 10 раз?
- Какие решения здесь обратимы, а какие почти нет?
- Кто будет поддерживать это через год?

> Архитектор делает не «самую правильную систему», а систему, которая выдерживает реальность.

## 2. Trade-offs и решения

В архитектуре нет бесплатных решений. Любой выбор покупает одно свойство ценой другого.

### Trade-off — best practice без контекста — плохой совет

> Внедорожник лучше седана на грязной дороге. Седан лучше внедорожника в городе. Велосипед лучше обоих, если тебе нужно проехать три квартала и негде парковаться.

Архитектурное решение нельзя оценивать вне контекста. REST, GraphQL, Kafka, PostgreSQL, Kubernetes, микросервисы, монолит — всё это инструменты с ценой. **Trade-off** — это осознанный обмен: latency против throughput, consistency против availability, time-to-market против maintainability, простота против гибкости.

Архитектор не говорит «Kafka лучше RabbitMQ». Он говорит: «нам нужен порядок событий по ключу, высокий throughput, replay и долговечный log; за это мы платим операционной сложностью Kafka». Так звучит профессиональный язык.

_Diagram: Каждое решение — точка на нескольких осях сразу. Сдвинулся к одному краю — отдал что-то на другом._

#### Trade-offs (осознанный обмен)

- **Что это:** Выбор, который покупает одно свойство ценой другого — и делается вслух.
- **Как работает:** Называешь, что выигрываешь, что теряешь, и почему эта цена приемлема сейчас.
- **Пример:** «Порядок по ключу, throughput, replay, durable log — платим операционной сложностью Kafka».
- **Подвох:** «X лучше Y» без контекста — не аргумент, а вкусовщина.
- **Связи:** **CAP / PACELC**, **over-engineering**, **sync vs async**.

### Over-engineering vs under-engineering — сложность как налог

> Каждая новая абстракция похожа на комнату в доме. Комната может быть полезной, но её нужно убирать, отапливать, ремонтировать и объяснять гостям, зачем она существует.

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

Термины **over-engineering** и **under-engineering** полезны только вместе. Over-engineering — когда сложность появилась раньше реальной боли. Under-engineering — когда система уже упёрлась в ограничения, а архитектура не оставила пути роста. Работа архитектора — не выбрать крайность, а удерживать середину.

_Diagram: Две ошибки по краям, правильная зона — посередине: сложность оправдана, только когда покупает конкретное свойство._

#### Over- / Under-engineering (переусложнение и недоусложнение)

- **Что это:** Over — сложность раньше реальной боли. Under — система упёрлась в пределы, пути роста нет.
- **Как работает:** Каждый новый слой или сервис должен назвать свойство, которое он покупает.
- **Пример:** Микросервисы и Kafka на старте для 200 пользователей — over. Одна таблица без индексов при росте в 10 раз — under.
- **Подвох:** Сложность «на будущее» не исчезает — её платят каждый день.
- **Связи:** **Trade-off**, **technical debt**, **cognitive load**.

> **Вопрос на каждое решение:** Что мы выигрываем, что теряем, и почему эта цена приемлема сейчас?

#### Что почитать

- Architecture: The Hard Parts — Ford, Richards, Sadalage, Dehghani
- Software Architecture in Practice — Bass, Clements, Kazman
- Martin Fowler: Is Design Dead?

## 3. Технический долг

Технический долг не всегда плох. Плох долг, который взяли случайно, не записали и не собираются возвращать.

### Technical debt — кредит, а не мусор

> Кредит на оборудование может ускорить бизнес. Кредит на вечеринку просто оставит похмелье и проценты.

**Technical debt** — это решение, которое ускоряет нас сейчас, но создаёт будущую стоимость изменения. Иногда это правильно: нужно проверить рынок, пройти дедлайн, сохранить клиента. Проблема начинается, когда команда называет долгом всё подряд: плохой код, отсутствие тестов, хаотичные зависимости, устаревшие библиотеки.

Полезная модель — **квадрант Мартина Фаулера (Technical Debt Quadrant)**: deliberate / inadvertent и prudent / reckless. Осознанный разумный долг: «мы временно не делаем multi-region, потому что у нас 200 пользователей и один рынок». Неосознанный безрассудный долг: «мы не знали, что транзакции нужны».

_Diagram: Квадрант Фаулера: брать долг можно осознанно и разумно (справа сверху). Опасны левые клетки._

#### Technical Debt (технический долг)

- **Что это:** Решение, которое ускоряет сейчас, но создаёт будущую стоимость изменения.
- **Как работает:** Берём осознанно, записываем «что и почему», ставим триггер пересмотра.
- **Пример:** «Не делаем multi-region: 200 пользователей, один рынок» — deliberate + prudent.
- **Подвох:** Если долгом зовут всё подряд — плохой код, нет тестов, старые библиотеки — слово теряет смысл.
- **Связи:** **Debt interest**, **ADR** (запись решения), **trade-off**.

### Debt interest — у долга есть проценты

> Если дорога разбита, каждая поездка занимает на пять минут больше. Через месяц это уже не выбоина, а налог на весь город.

Проценты по техническому долгу — это замедление каждого следующего изменения. Чем чаще команда трогает участок, тем дороже долг. Поэтому долг в горячем домене опаснее, чем долг в редко используемой админке.

Архитектор договаривается о стратегии выплаты: что именно считаем долгом, какой риск он создаёт, когда пересматриваем решение, какой сигнал говорит «пора платить». Без этого «технический долг» становится эмоциональным аргументом, а не управляемым инструментом.

_Diagram: Один и тот же долг: в горячем домене проценты капают с каждой правкой, в админке — почти нет._

#### Debt Interest (проценты по долгу)

- **Что это:** Замедление каждого следующего изменения в «задолженном» коде.
- **Как работает:** Проценты ≈ замедление × как часто команда трогает этот участок.
- **Пример:** Долг в оплате, которую правят каждую неделю, дороже долга в админке, которую открывают раз в квартал.
- **Подвох:** Без стратегии выплаты «техдолг» превращается в эмоциональный аргумент.
- **Связи:** **Technical debt**, **cognitive load**.

> **Ключевой вопрос:** Этот долг помогает нам купить время или просто маскирует плохое решение?

#### Вопросы для ревью долга

- Где записано, почему мы приняли этот компромисс?
- Какой процент мы платим каждый спринт?
- Что должно случиться, чтобы долг стал блокером?
- Есть ли план выплаты или хотя бы триггер пересмотра?

## 4. Cognitive load

Система, которую никто не может удержать в голове, будет ломаться даже при хороших инженерах.

### Cognitive load — архитектура должна помещаться в голову

> Карта метро полезна не потому, что показывает каждый болт в тоннеле. Она показывает линии, пересадки и направление движения. Этого достаточно, чтобы принять решение.

**Cognitive load** — это умственная нагрузка, которую система требует от инженера. Есть **intrinsic load**: сложность самой предметной области. Есть **extraneous load**: лишняя сложность от плохой архитектуры, неочевидных связей, случайных исключений и магии. Архитектор не может убрать сложность бизнеса, но обязан снижать лишнюю сложность.

Хороший модуль можно понять отдельно. Хороший bounded context имеет свой язык и свои инварианты. Хорошая команда владеет областью, которая помещается в её голову.

_Diagram: Сложность домена (intrinsic) остаётся всегда. Архитектура решает, сколько лишней (extraneous) ляжет сверху — и влезет ли всё в голову._

#### Cognitive Load (когнитивная нагрузка)

- **Что это:** Сколько контекста инженер должен держать в голове, чтобы безопасно что-то изменить.
- **Как работает:** Intrinsic — сложность домена, её не убрать. Extraneous — лишняя, её надо резать.
- **Пример:** Модуль, который понятен сам по себе, против модуля, где без «магии» и исключений ничего не понять.
- **Подвох:** Хорошие инженеры не спасают систему, которая не помещается в голову.
- **Связи:** **Bounded context**, **Conway's Law**, **decomposition**.

### Conway's Law — структура команд становится структурой системы

> Если три отдела не разговаривают друг с другом, их продукт почти всегда выглядит как три продукта, склеенные в одном меню.

**Conway's Law** говорит: организация проектирует системы, похожие на структуру коммуникации внутри организации. Если архитектурные границы не совпадают с командными границами, команда будет постоянно пересекать чужую территорию.

**Team Topologies** вводит полезные термины: stream-aligned team, platform team, enabling team, complicated-subsystem team. Это не HR-мода, а архитектурный инструмент: иногда правильная декомпозиция системы начинается с правильной декомпозиции ответственности.

_Diagram: Закон Конвея: система повторяет структуру общения команд. Team Topologies даёт четыре типа команд для осознанной нарезки._

#### Conway's Law (закон Конвея + Team Topologies)

- **Что это:** Система повторяет структуру коммуникации организации, которая её строит.
- **Как работает:** Границы команд и границы системы выравнивают: каждая команда владеет своей областью.
- **Пример:** Три отдела, которые не общаются, выпускают «три продукта в одном меню».
- **Подвох:** Если границы не совпадают, команды постоянно лезут на чужую территорию.
- **Связи:** **Team Topologies** (stream-aligned, platform, enabling, complicated-subsystem), **bounded context**.

> **Ключевой вопрос:** Сколько контекста нужно загрузить инженеру, чтобы безопасно изменить этот компонент?

## 5. Декомпозиция системы

Большая система становится управляемой только тогда, когда её можно разрезать по правильным границам.

### Cohesion & coupling — резать по слоям, по доменам и по потоку данных

> Мясник режет тушу не как попало, а по суставам. Хорошая декомпозиция тоже ищет естественные места разрыва.

Декомпозиция — это не «разложить по папкам». Это выбор границ ответственности. **High cohesion** означает, что внутри компонента всё связано одной темой. **Low coupling** означает, что компонент мало знает о других компонентах.

Горизонтальный разрез даёт **слои (layers)**: UI, application, domain, infrastructure. Вертикальный разрез даёт фичи или **bounded contexts**: billing, identity, catalog, comments. В реальных системах нужны оба, но опасно путать одно с другим.

_Diagram: Горизонтальный разрез — слои, вертикальный — фичи и контексты. Реальная система — это сетка из обоих._

#### Cohesion & Coupling (связность внутри, слабая связь снаружи)

- **Что это:** Внутри компонента всё про одно (cohesion); снаружи он мало знает о других (coupling).
- **Как работает:** Режешь горизонтально (слои) и вертикально (фичи / контексты) — и не путаешь эти разрезы.
- **Пример:** Модуль `billing` со своими слоями UI → application → domain → infra.
- **Подвох:** «Разложить по папкам» — ещё не декомпозиция.
- **Связи:** **Bounded context**, **layers**, **modular monolith**.

### Bounded context — плохая граница выдаёт себя изменениями

> Если чтобы заменить кран на кухне нужно разобрать спальню, проблема не в кране.

Признак плохой декомпозиции: маленькое изменение расползается по пяти модулям. Ещё один признак: один модуль меняется по разным причинам — сегодня из-за продукта, завтра из-за базы, послезавтра из-за интеграции.

DDD-термин **bounded context** полезен именно здесь. Это граница, внутри которой слова имеют один смысл. Например, «Customer» в billing и «Customer» в support могут быть разными моделями. Насильственное объединение таких понятий часто создаёт хрупкую «универсальную» модель.

_Diagram: Одно слово — две модели: Customer в биллинге и Customer в поддержке значат разное, и это нормально._

#### Bounded Context (ограниченный контекст (DDD))

- **Проблема:** Маленькая правка расползается по пяти модулям; один модуль меняется по разным причинам.
- **Идея:** Граница, внутри которой каждое слово имеет один смысл и одну модель.
- **Пример:** «Customer» в billing и «Customer» в support — разные модели.
- **Цена:** Модели надо сопоставлять на границах; появляется перевод между контекстами.
- **Когда брать:** Когда одно понятие значит разное для разных частей бизнеса.
- **Связи:** **Cohesion / coupling**, **Conway's Law**, **microservices**.

> **Тест декомпозиции:** Могу ли я объяснить этот компонент, не рассказывая половину системы?

## 6. Слои и направление зависимостей

Бизнес-логика должна зависеть от правил бизнеса, а не от фреймворка, базы данных или HTTP.

### Dependency Rule и DIP — зависимости текут к центру

> Фундамент не должен зависеть от цвета штор. Если зависит — дом спроектирован наоборот.

**Clean Architecture**, **Hexagonal Architecture** и **Onion Architecture** говорят об одном: важная логика должна быть в центре, детали — снаружи. HTTP, SQLAlchemy, Next.js, Kafka, Redis, Stripe — это детали. Они важны, но они не должны определять бизнес-правила.

**Dependency Inversion Principle** означает: высокоуровневая логика зависит от абстракций, а реализации подключаются снаружи. В коде это выглядит как ports and adapters: service получает `PaymentGatewayProtocol`, а не создаёт `StripeClient` внутри себя.

_Diagram: Домен в центре зависит только от порта. StripeClient, HTTP и база — детали снаружи, все стрелки смотрят внутрь._

#### Dependency Inversion (DIP, правило зависимостей)

- **Проблема:** Бизнес-правила вросли во фреймворк и базу — их не протестировать и не заменить.
- **Идея:** Высокоуровневая логика зависит от абстракций; реализации подключаются снаружи.
- **Пример:** Сервис получает `PaymentGatewayProtocol`, а не создаёт `StripeClient` внутри себя.
- **Цена:** Больше интерфейсов и файлов.
- **Когда брать:** Есть реальные бизнес-правила, которые должны пережить смену технологий.
- **Связи:** **Clean / Hexagonal / Onion Architecture**, **ports and adapters**.

### Abstraction — нужна под давлением изменений, а не для красоты

> Переходник нужен там, где вилки действительно разные. Если ты вставляешь переходник в каждую розетку просто потому что любишь переходники, дом становится опаснее.

Не каждый класс требует интерфейса. Но всё, что связано с внешним миром, временем, случайностью, сетью, файловой системой и базой данных, должно быть заменяемо в тестах. Иначе ты не тестируешь бизнес-логику, а запускаешь маленькую production-систему в unit-тесте.

Цена слоя — больше файлов и больше слов. Выигрыш — тестируемость, сменяемость инфраструктуры, ясные границы. Если выигрыша нет, слой лишний.

_Diagram: Внешний мир (время, случайность, сеть, файлы, база) прячем за порт — в тестах подставляем fake. Чистой логике интерфейс не нужен._

#### Abstraction (абстракция там, где давят изменения)

- **Что это:** Интерфейс вводится там, где реализация реально меняется или мешает тестам.
- **Как работает:** Время, случайность, сеть, файлы, база → за порт; в тестах — fake, в проде — настоящий адаптер.
- **Пример:** Бизнес-правило тестируется без базы, HTTP и реального времени — за миллисекунды.
- **Подвох:** Слой без выигрыша — лишние файлы и слова, а не архитектура.
- **Связи:** **DIP**, **testability**, **over-engineering**.

> **Ключевой вопрос:** Можно ли протестировать бизнес-правило без базы данных, HTTP и реального времени?

## 7. API и контракты

API — это обещание. Сломать обещание легко; вернуть доверие клиентов трудно.

### API contract — контракт важнее транспорта

> Паспортный контроль не зависит от марки двери. Важно, какие документы принимают, какие правила действуют и что будет при ошибке.

**REST**, **GraphQL**, **gRPC** и **WebSocket** — разные способы общения. REST хорош для resource-oriented API и простого кэширования. GraphQL полезен, когда клиентам нужны разные формы чтения. gRPC хорош для typed service-to-service коммуникации. WebSocket нужен для двусторонних событий в реальном времени.

Выбор транспорта вторичен. Главное — **контракт (API contract)**: схема, ошибки, идемпотентность, версионирование, **backward compatibility**, **deprecation policy**.

_Diagram: Транспорт слева можно поменять. Контракт справа — обещание клиентам, его ломать дорого._

#### API Contract (контракт API)

- **Что это:** Обещание клиентам: схема, ошибки, идемпотентность, версии, совместимость, правила отказа от старого.
- **Как работает:** Сначала договариваемся о контракте, потом выбираем транспорт под задачу.
- **Пример:** REST — ресурсы и кэш; GraphQL — разные формы чтения; gRPC — типизированно между сервисами; WebSocket — real-time.
- **Подвох:** Сломать обещание легко, вернуть доверие клиентов трудно.
- **Связи:** **Idempotency**, **versioning**, **reversible vs irreversible**.

### Idempotency — спасение от реального мира

> Если ты нажал кнопку лифта десять раз, лифт не должен десять раз приехать и уехать. Он должен понять, что намерение одно.

**Idempotency** означает, что повтор операции даёт тот же итоговый эффект. В сетевых системах повторы неизбежны: timeout, retry, дубль webhook, перезапуск worker-а. Если создание платежа, заказа или сообщения не идемпотентно, система рано или поздно сделает лишнее.

Архитектор проектирует идемпотентность на уровне контракта: **idempotency key**, уникальные constraints, безопасные retry, понятные статусы.

_Diagram: Клиент повторил запрос трижды с одним ключом — сервер узнал ключ, и платёж создан один раз._

#### Idempotency (идемпотентность)

- **Что это:** Повтор операции даёт тот же итоговый эффект, что и первый вызов.
- **Как работает:** Idempotency key в запросе + уникальный constraint в базе + понятные статусы.
- **Пример:** Timeout при оплате → клиент повторяет `POST /payments` с тем же ключом → деньги списаны один раз.
- **Подвох:** Без неё повторы (retry, дубль webhook, рестарт worker-а) рано или поздно сделают лишнее.
- **Связи:** **At-least-once delivery**, **API contract**, **retries**.

> **Ключевой вопрос:** Что произойдёт, если клиент повторит этот запрос три раза?

## 8. Модель данных

Код переписывают. Данные мигрируют годами. Поэтому модель данных — одно из самых дорогих архитектурных решений.

### Data model — данные живут дольше приложений

> Фасад здания можно перекрасить за неделю. Фундамент, залитый неправильно, будет напоминать о себе весь срок жизни здания.

Язык, фреймворк и UI могут смениться несколько раз. Но таблицы, события, ключи, связи и исторические записи остаются. Ошибка в модели данных часто становится ошибкой всех будущих версий продукта.

**Нормализация (normalization)** снижает дублирование и риск рассинхрона. **Денормализация (denormalization)** ускоряет чтение и упрощает read model. **OLTP** системы оптимизированы под транзакции, **OLAP** — под аналитику. Нельзя проектировать одну модель так, будто она идеально решит оба класса задач.

_Diagram: Приложение переписали трижды, а данные остались. Внизу — два разных класса задач: транзакции (OLTP) и аналитика (OLAP)._

#### Data Model (модель данных · OLTP / OLAP)

- **Что это:** Таблицы, события, ключи, связи и история — то, что переживает все переписывания кода.
- **Как работает:** Нормализация — меньше дублей и рассинхрона; денормализация — быстрее чтение.
- **Пример:** OLTP-база для заказов и отдельное OLAP-хранилище для отчётов.
- **Подвох:** Ошибка в модели данных становится ошибкой всех будущих версий продукта.
- **Связи:** **Irreversible decisions**, **event sourcing**, **CQRS**.

### Event sourcing и CQRS — сильный инструмент, не религия

> Банковская выписка хранит не только текущий баланс, а историю операций. Это позволяет объяснить, откуда баланс взялся.

**Event sourcing** хранит изменения как последовательность событий, а текущее состояние строит из них. Это полезно, когда важна история, аудит, восстановление состояния, replay. Но цена высокая: schema evolution событий, сложность запросов, eventual consistency, требования к tooling.

**CQRS** разделяет write model и read model. Это может сильно упростить сложные системы чтения, но добавляет синхронизацию и задержки. Вводить CQRS только потому что «так архитектурно» — дорогой способ получить две проблемы вместо одной.

_Diagram: Команда пишет события в журнал; проекция строит из них read model, которую читают запросы._

#### Event Sourcing (хранение событий)

- **Проблема:** Текущее состояние не объясняет, как мы к нему пришли.
- **Идея:** Храним изменения как журнал событий; состояние = их проигрывание (replay).
- **Пример:** Банковская выписка: баланс складывается из операций.
- **Цена:** Эволюция схемы событий, сложные запросы, eventual consistency, требования к tooling.
- **Когда брать:** Важны история, аудит, восстановление состояния, replay.
- **Связи:** Часто идёт вместе с **CQRS**.

#### CQRS (Command Query Responsibility Segregation)

- **Проблема:** Одна модель плохо обслуживает и запись, и сложные чтения.
- **Идея:** Разделить write model и read model.
- **Пример:** Заказы пишутся в нормализованную модель, а экран отчётов читает готовую витрину.
- **Цена:** Синхронизация и задержка между моделями.
- **Когда брать:** Когда чтение действительно сложное — а не потому, что «так архитектурно».
- **Связи:** **Event sourcing**, **denormalization**, **eventual consistency**.

> **Ключевой вопрос:** Какие факты этой системы должны пережить три переписывания приложения?

## 9. Состояние и источник правды

Состояние — это сложность, которая где-то хранится. Чем больше копий правды, тем больше способов ошибиться.

### Single source of truth — не значит single database

> В компании может быть много отчётов, но должен быть один официальный реестр зарплат. Иначе в день выплат начнётся театр.

**Single source of truth** означает, что для каждого важного факта понятно, где живёт авторитетная версия. Кэш, поисковый индекс, read replica, materialized view — это производные копии. Они могут быть полезны, но не должны притворяться первичной правдой.

**Stateful** компоненты хранят состояние и требуют аккуратности: транзакции, locking, recovery, backup. **Stateless** компоненты проще масштабировать и заменять, но они всё равно зависят от состояния где-то ещё.

_Diagram: Слева — stateless-приложения, в центре — одна авторитетная база, справа — производные копии, которые правдой не являются._

#### Single Source of Truth (единый источник правды)

- **Что это:** Для каждого важного факта ясно, где живёт его авторитетная версия.
- **Как работает:** Одна первичная запись; кэш, индекс, реплика, витрина — производные копии.
- **Пример:** Много отчётов, но один официальный реестр зарплат.
- **Подвох:** Не значит «одна база на всё» — значит «один хозяин у каждого факта».
- **Связи:** **Stateful / stateless**, **cache**, **CQRS**.

### Cache и locking — вторая правда, которая иногда врёт

> Расписание на холодильнике удобно, пока кто-то не перенёс встречу в календаре телефона.

**Кэш (cache)** покупает скорость ценой свежести. Самый сложный вопрос кэша — не «как положить», а «когда инвалидировать». **TTL**, **explicit invalidation**, **write-through**, **write-behind**, **cache-aside** — это разные компромиссы между сложностью, свежестью и нагрузкой.

_Diagram: Cache-aside: читаем кэш, при промахе идём в базу и кладём ответ в кэш. Справа — стратегии инвалидации._

**Race condition** появляется, когда две операции конкурируют за состояние. **Optimistic locking** говорит: «конфликты редки, проверим версию при записи». **Pessimistic locking** говорит: «конфликты опасны, заблокируем заранее». Оба подхода правильны в разных условиях.

_Diagram: Слева оптимистичная блокировка ловит конфликт по версии при записи. Справа пессимистичная заставляет второго ждать._

#### Cache Invalidation (кэш и его инвалидация)

- **Что это:** Копия данных ближе к читателю: скорость в обмен на свежесть.
- **Как работает:** TTL, explicit invalidation, write-through, write-behind, cache-aside — разные компромиссы.
- **Пример:** Расписание на холодильнике против календаря в телефоне.
- **Подвох:** Главный вопрос — не «как положить», а «когда выкинуть».
- **Связи:** **Single source of truth**, **eventual consistency**.

#### Optimistic vs Pessimistic Locking (оптимистичная и пессимистичная блокировка)

- **Что это:** Два способа не дать двум операциям испортить общее состояние (race condition).
- **Как работает:** Optimistic — проверяем версию при записи. Pessimistic — блокируем заранее.
- **Пример:** Два менеджера правят одну карточку: второй получает конфликт и перечитывает данные.
- **Подвох:** Optimistic плох при частых конфликтах, pessimistic — при высокой конкуренции за блокировки.
- **Связи:** **Transactions**, **stateful components**.

> **Ключевой вопрос:** Где живёт правда о каждом факте, и что произойдёт, если копии разойдутся?

## 10. Распределённые системы

Распределённость решает проблемы масштаба, но создаёт проблемы времени, порядка и доверия к сети.

### CAP и PACELC — сеть как источник неопределённости

> Монолит — разговор в одной комнате. Распределённая система — переписка между людьми в разных часовых поясах, где письма иногда теряются, приходят дважды или задерживаются.

В распределённой системе нельзя просто «вызвать функцию». Между сервисами есть сеть, timeout, retry, **partial failure**, разные часы, разные версии кода. То, что в монолите было локальной транзакцией, становится протоколом координации.

**CAP theorem** часто пересказывают плохо. Практически полезнее помнить: при **network partition** ты выбираешь между consistency и availability. **PACELC** добавляет: даже когда partition нет, ты всё равно выбираешь между latency и consistency.

_Diagram: Связь между узлами порвалась — выбирай: согласованность или доступность. Нет обрыва — всё равно выбираешь: задержка или согласованность._

#### CAP / PACELC (теоремы о выборе в распределённых системах)

- **Что это:** При разрыве сети — C или A (CAP). Без разрыва — L или C (PACELC).
- **Как работает:** Каждое хранилище и каждый сценарий явно выбирает, чем жертвует.
- **Пример:** Узел без связи с соседом: отказать (C) или ответить, возможно, устаревшим (A).
- **Подвох:** «Мы выбрали CA» в сети не бывает: разрывы случаются, вопрос только — что делаем тогда.
- **Связи:** **Consistency models**, **trade-off**, **partial failure**.

### Consistency models и Saga — согласованность бывает разной

> Если два человека смотрят один документ в Google Docs, они почти сразу видят одно и то же. Если два человека смотрят банковский перевод, «почти» уже недостаточно.

**Strong consistency** даёт свежую правду, но стоит latency и availability. **Eventual consistency** допускает временный рассинхрон, но часто лучше масштабируется. **Causal consistency** сохраняет причинный порядок: если событие B зависит от A, B не должно быть видно раньше A.

_Diagram: Шкала согласованности: от eventual (масштабируется, допускает рассинхрон) до strong (свежо, но дороже)._

**Saga pattern** помогает разложить длинную бизнес-транзакцию на шаги с **compensating actions**. **Two-phase commit** даёт атомарность между ресурсами, но дорог и хрупок в реальных распределённых системах. Архитектор выбирает не «самую строгую» модель, а достаточную для риска.

_Diagram: Saga: шаг 3 упал — компенсирующие действия откатывают уже сделанные шаги 2 и 1 в обратном порядке._

#### Consistency Models (strong · causal · eventual)

- **Что это:** Насколько быстро и в каком порядке все видят одну и ту же правду.
- **Как работает:** Strong — всегда свежо; causal — сохраняет причинный порядок; eventual — догонит позже.
- **Пример:** Общий документ: «почти сразу» нормально. Банковский перевод: нет.
- **Подвох:** Strong платит latency и availability; eventual — временным рассинхроном.
- **Связи:** **CAP / PACELC**, **cache**, **CQRS**.

#### Saga (длинная транзакция с компенсациями)

- **Проблема:** Бизнес-операция идёт через несколько сервисов; общей транзакции нет.
- **Идея:** Цепочка шагов; если шаг упал — компенсирующие действия отменяют сделанное.
- **Пример:** Резерв товара → списание → доставка упала → возврат денег → снятие резерва.
- **Цена:** Каждому шагу нужна компенсация; промежуточные состояния видны.
- **Когда брать:** Вместо **two-phase commit**, который дорог и хрупок в распределённой системе.
- **Связи:** **Eventual consistency**, **idempotency**, **microservices**.

> **Ключевой вопрос:** Что именно должно быть согласовано немедленно, а что может догнать позже?

## 11. Монолит и микросервисы

Микросервисы не лечат плохой дизайн. Они превращают локальные проблемы в распределённые.

### Modular monolith — часто недооценённый старт

> Один хорошо организованный склад быстрее десяти маленьких складов, если между ними всё равно ездит один и тот же курьер.

Монолит — не оскорбление. Плохой монолит — это ком грязных зависимостей. Хороший **modular monolith** имеет строгие внутренние границы, отдельные домены, явные интерфейсы и одну **deployment unit**. Для маленькой команды это часто лучший старт.

**Микросервисы (microservices)** помогают, когда нужны независимые релизы, автономные команды, разные scaling profiles, изоляция отказов, разные технологические стеки. Но цена: network calls, observability, distributed transactions, DevOps overhead, versioning, security между сервисами.

_Diagram: Слева — одна единица деплоя с крепкими стенами внутри. Справа — отдельные сервисы со своими базами и счётом за сеть._

#### Modular Monolith (модульный монолит)

- **Проблема:** Монолит превращается в ком грязных зависимостей.
- **Идея:** Строгие внутренние границы и явные интерфейсы — но одна deployment unit.
- **Пример:** Модули billing, identity, catalog в одном приложении, общаются через API модулей.
- **Цена:** Нужна дисциплина границ; масштабируется и релизится целиком.
- **Когда брать:** Маленькая команда, старт продукта. **Microservices** — когда нужны независимые релизы, автономные команды, разные профили нагрузки, изоляция отказов.
- **Связи:** **Bounded context**, **microservices**, **Strangler Fig**.

### Distributed monolith и Strangler Fig — худшее из двух миров и выход

> Это как жить в разных квартирах, но ходить друг к другу за каждой ложкой.

**Distributed monolith** выглядит как микросервисы, но сервисы не автономны: общий database schema, синхронные цепочки вызовов, релизы только вместе, изменения требуют трогать всех. Команда платит стоимость распределённости, не получая независимости.

_Diagram: Distributed monolith: сервисы связаны синхронной цепочкой и общей схемой базы — независимости нет._

**Strangler Fig pattern** помогает мигрировать аккуратно: оборачиваем старую систему, постепенно выносим capabilities, режем по реальной бизнес-границе, а не по таблицам.

_Diagram: Strangler Fig: фасад перед старой системой по одной выносит способности в новые сервисы, пока старое не исчезнет._

#### Distributed Monolith (распределённый монолит)

- **Признаки:** Общая схема базы, синхронные цепочки вызовов, релизы только вместе, правка трогает всех.
- **Почему плохо:** Платишь за распределённость, а независимости не получаешь.
- **Пример:** Разные квартиры, но за каждой ложкой — к соседу.
- **Как выйти:** Свои данные у каждого сервиса, асинхронные связи, границы по бизнес-смыслу — или обратно в модульный монолит.
- **Связи:** **Modular monolith**, **bounded context**, **sync vs async**.

#### Strangler Fig (фикус-душитель)

- **Проблема:** Старую систему нельзя переписать за один раз.
- **Идея:** Обернуть её фасадом и постепенно выносить способности (capabilities) в новые сервисы.
- **Пример:** Сначала выносим billing, потом catalog — фасад направляет запросы.
- **Цена:** Долгое время живут две системы сразу.
- **Когда брать:** Миграция живой системы без «большого переписывания».
- **Связи:** Режем по **bounded context**, а не по таблицам.

> **Ключевой вопрос:** Какую боль мы лечим микросервисами: нагрузку, команды, релизы, отказоустойчивость — или просто скуку?

## 12. Синхронность и асинхронность

Sync связывает системы во времени. Async разрывает эту связь, но приносит задержки, дубли и сложность порядка.

### Queue и pub/sub — очередь это не просто «потом»

> Телефонный звонок требует, чтобы оба были свободны сейчас. Письмо можно прочитать позже, но оно может затеряться, прийти с задержкой или потребовать ответа.

**Синхронный запрос (sync)** прост для понимания: отправил, получил ответ. Но если получатель медленный или недоступен, отправитель страдает. **Асинхронность (async)** через **queue** или **pub/sub** позволяет пережить сбои и пики нагрузки, но требует другой модели мышления.

Queue обычно распределяет работу между consumer-ами. Pub/sub рассылает событие многим подписчикам. Kafka, RabbitMQ, SQS, Redis Streams — разные инструменты с разной моделью ordering, durability, replay и operations.

_Diagram: Sync: отправитель ждёт. Queue: каждое сообщение берёт один worker. Pub/sub: каждое событие получает каждый подписчик._

#### Queue vs Pub/Sub (очередь и публикация-подписка)

- **Проблема:** Синхронный вызов связывает системы во времени: упал получатель — страдает отправитель.
- **Идея:** Queue делит работу между consumer-ами; pub/sub рассылает событие всем подписчикам.
- **Пример:** Kafka, RabbitMQ, SQS, Redis Streams — разные ordering, durability, replay.
- **Цена:** Задержки, дубли, сложность порядка.
- **Когда брать:** Отправителю не нужен результат прямо сейчас; надо пережить сбои и пики.
- **Связи:** **At-least-once delivery**, **backpressure**, **idempotency**.

### At-least-once delivery — exactly-once почти всегда маркетинг

> Если письмо отправили дважды, правильная бухгалтерия не должна дважды выплатить зарплату.

В реальности чаще проектируют **at-least-once delivery** плюс **идемпотентный consumer**. Сообщение может прийти дважды; обработчик должен пережить это. **Dead letter queue** нужна для сообщений, которые не получилось обработать после разумного числа попыток.

**Backpressure** — сигнал «получатель не успевает». Без него система красиво принимает всё, а потом умирает внутри.

_Diagram: Сообщение может прийти дважды — consumer отсеивает дубли по id. После N неудач — в DLQ. Backpressure просит отправителя притормозить._

#### At-least-once Delivery (доставка «хотя бы раз» + DLQ + backpressure)

- **Что это:** Сообщение гарантированно дойдёт, но, возможно, не один раз.
- **Как работает:** Идемпотентный consumer отсеивает дубли; dead letter queue собирает сообщения после N неудач; backpressure говорит «не успеваю».
- **Пример:** Дубль сообщения «выплатить зарплату» не выплачивает её дважды.
- **Подвох:** «Exactly-once» почти всегда маркетинг; без backpressure система принимает всё и умирает внутри.
- **Связи:** **Idempotency**, **queue / pub/sub**, **reliability**.

> **Ключевой вопрос:** Нужно ли отправителю знать результат прямо сейчас, или достаточно гарантированно поставить работу в процесс?

## 13. Производительность и измерения

«Сделать быстро» — не требование. Требование звучит как latency, throughput, percentiles и нагрузочный профиль.

### Tail Latency — среднее время ответа почти всегда врёт

> Если девять человек получили еду за минуту, а десятый ждал час, среднее выглядит терпимо. Десятый так не думает.

Это понятие **tail latency** — хвостовая задержка. Сначала три слова. **Latency** — задержка одной операции. **Throughput** — сколько операций система делает за единицу времени. **Percentiles** показывают распределение: **p50** — медиана, **p95** — 95% запросов быстрее этого значения, **p99** — хвост.

Пользователь чувствует не среднее, а хвост. Tail latency особенно важна там, где один экран зависит от нескольких backend-вызовов: вероятность медленного ответа складывается.

_Diagram: Большинство запросов быстрые, но хвост (p95, p99) длинный. Среднее его прячет, а пользователь его чувствует._

#### Tail Latency (p95 / p99, хвостовая задержка)

- **Проблема:** Среднее время ответа выглядит хорошо, а часть пользователей ждёт очень долго.
- **Идея:** Смотреть на percentiles: p50 — медиана, p95 и p99 — хвост.
- **Пример:** Экран собирается из пяти backend-вызовов: если хоть один попал в хвост, медленным становится весь экран.
- **Цена:** Нужно собирать распределение, а не одно число; нужны гистограммы в метриках.
- **Когда брать:** Всегда, когда формулируешь требование «быстро» и строишь SLO.
- **Связи:** Основа для **SLO**; растёт при **retry storm**; видна через **observability**.

### Profiling — профилировать до оптимизации

> Чинить производительность без профиля — как лечить пациента по фотографии обуви.

Это практика **profiling**: сначала измерить, потом оптимизировать. N+1 query, лишние round trips, плохой индекс, сериализация, lock contention, GC pause, холодный cache — все они выглядят как «медленно», но лечатся по-разному.

**Amdahl's Law** напоминает: ускорение ограничено частью системы, которую ты реально оптимизируешь. **Little's Law** помогает думать об очередях: больше latency при том же throughput означает больше work-in-progress внутри системы.

_Diagram: Цикл: измерить → профилировать → найти горячую точку → исправить одно → измерить снова. Внизу — два закона, которые ограничивают ожидания._

#### Profiling (сначала измерь, потом оптимизируй)

- **Проблема:** Команда «ускоряет» не то место: тратит неделю, а система не стала быстрее.
- **Идея:** Профиль показывает, где реально уходит время. Чинить только горячую точку.
- **Пример:** «Медленная страница» оказывается N+1 query, а не медленным языком — лечится одним запросом с join.
- **Цена:** Время на измерения и инструменты; нужен воспроизводимый нагрузочный профиль.
- **Когда брать:** Перед любой оптимизацией. Без профиля — не оптимизировать.
- **Связи:** **Amdahl's Law** — потолок ускорения; **Little's Law** — связь latency, throughput и очередей.

> **Ключевой вопрос:** Какая метрика станет красной первой при реальной нагрузке?

## 14. Масштабируемость без переписывания

Масштабируемость — это способность расти по нагрузке и функциям без полного пересоздания системы.

### Vertical vs Horizontal Scaling — покупают разное

> Можно купить один большой грузовик. Можно купить десять маленьких. Первый проще, вторые гибче, но требуют диспетчера.

**Vertical scaling** (scale up) — усилить одну машину. Просто, пока хватает потолка. **Horizontal scaling** (scale out) — добавить больше экземпляров. Гибче, но требует stateless application layer, load balancing, shared state strategy и наблюдаемости.

Базы масштабируются сложнее приложений. **Read replicas** помогают чтению, но не записи. **Sharding** делит данные, но заставляет выбрать shard key. Плохой shard key превращает масштабирование в перекос нагрузки.

_Diagram: Слева — одна машина растёт до потолка железа. Справа — балансировщик и много одинаковых stateless-копий. Внизу — два способа масштабировать базу._

#### Vertical vs Horizontal Scaling (scale up / scale out)

- **Проблема:** Нагрузка растёт, одной машины скоро не хватит.
- **Идея:** Vertical — сделать машину сильнее. Horizontal — поставить больше машин за load balancer.
- **Пример:** Приложение без состояния легко размножить; база — сложнее: read replicas для чтения, sharding по shard key для записи.
- **Цена:** Vertical упирается в потолок. Horizontal требует stateless-слоя, балансировки, стратегии общего состояния и наблюдаемости.
- **Когда брать:** Vertical — пока хватает потолка. Horizontal — когда нужен рост дальше.
- **Связи:** X-ось **Scale Cube**; **stateless** компоненты из темы о состоянии; **Single Source of Truth**.

### Scale Cube — масштабирование функций не менее важно

> Город растёт не только количеством жителей. Он растёт школами, больницами, дорогами и правилами.

Система должна выдерживать не только больше traffic, но и больше product surface. Если каждая новая фича требует переписать общий God-service, система не масштабируется организационно.

Полезная модель здесь — **scaling cube**: **X-axis** — клонирование, **Y-axis** — разделение по функциям, **Z-axis** — partitioning по данным или tenants.

_Diagram: Три оси роста: X — копии одного приложения, Y — разные функции в разных частях, Z — данные или клиенты поделены на партиции._

#### Scale Cube (куб масштабирования, X/Y/Z)

- **Проблема:** Думают только о трафике, а система ломается от роста функций: всё живёт в одном God-service.
- **Идея:** Расти по трём осям: X — клонировать, Y — делить по функциям, Z — делить по данным или tenants.
- **Пример:** X: три копии приложения. Y: billing, catalog, identity отдельно. Z: tenants A–H на одном шарде, I–P на другом.
- **Цена:** Каждая ось добавляет границы, которые надо держать и наблюдать.
- **Когда брать:** Когда спрашиваешь «что сломается первым» — и ответ не только CPU.
- **Связи:** Y-ось — это **Bounded Context** и микросервисы; Z-ось — sharding; учитывай **Conway's Law**.

> **Ключевой вопрос:** Что сломается первым: CPU, база, команда, релизы или модель данных?

## 15. Надёжность под сбоем

Надёжная система не та, где ничего не ломается. Надёжная система знает, что делать, когда ломается.

### Retry, Circuit Breaker, Bulkhead — retry без стратегии создаёт атаку на самого себя

> Если дверь не открылась, один раз постучать разумно. Стучать тысячу раз в секунду — уже проблема для двери и соседей.

**Retry** нужен для transient failures. Но retry должен иметь лимит, timeout, **exponential backoff** и **jitter**. Иначе частичный сбой превращается в **retry storm**.

**Circuit breaker** временно прекращает вызовы к зависшему dependency. **Bulkhead pattern** изолирует ресурсы: если один downstream умирает, он не забирает все worker threads и connection pools.

_Diagram: Сверху — повторы с растущей паузой и случайным сдвигом. Снизу — отдельные пулы (bulkheads) и circuit breaker: зависший Payments API не утягивает за собой поиск._

#### Retry + Circuit Breaker + Bulkhead (устойчивость к сбоям зависимостей)

- **Проблема:** Зависимость тормозит или падает; бездумные повторы добивают её и забирают все ресурсы у сервиса.
- **Идея:** Retry — с лимитом, timeout, backoff и jitter. Circuit breaker — перестать звать мёртвое. Bulkhead — отдельные пулы, чтобы сбой не расползся.
- **Пример:** Платёжный API завис: breaker размыкается и сразу отвечает ошибкой, а пул для поиска продолжает работать.
- **Цена:** Больше настроек и состояний; нужно решить, как система деградирует, когда зависимость недоступна.
- **Когда брать:** Любой сетевой вызов к тому, что может зависнуть.
- **Связи:** Повторы безопасны только с **Idempotency**; связано с **at-least-once** и **backpressure**.

### SLI / SLO / SLA — SLO превращает надёжность в контракт

> «Будем стараться» — не расписание поездов. Расписание говорит, что считается нормой, а что сбоем.

**SLI** — что измеряем: success rate, latency, freshness. **SLO** — целевой уровень: 99.9% успешных запросов за 30 дней. **SLA** — обещание клиенту с последствиями.

**Error budget** говорит, сколько ненадёжности мы можем потратить. Если бюджет сгорел, команда перестаёт гнаться за фичами и чинит надёжность. Это бизнесовый язык для инженерного качества.

_Diagram: SLI — измерение, SLO — цель, SLA — обещание клиенту. При SLO 99.9% бюджет ошибок — 0.1%, около 43 минут за 30 дней._

#### SLI / SLO / SLA (error budget, бюджет ошибок)

- **Проблема:** «Надёжно» никто не измерил, поэтому спор фичи против качества бесконечен.
- **Идея:** Измерять (SLI), договориться о цели (SLO), отдельно — обещание клиенту (SLA). Разница с 100% — бюджет ошибок.
- **Пример:** SLO: 99.9% успешных запросов за 30 дней. Бюджет сгорел — фичи на паузу.
- **Цена:** Нужно честно выбрать, что измерять, и соблюдать правило, когда бюджет кончился.
- **Когда брать:** Когда надёжность надо обсуждать с бизнесом на одном языке.
- **Связи:** SLI часто строят на **Tail Latency**; алерты — по **symptoms**; это **NFR** в цифрах.

> **Ключевой вопрос:** Как система деградирует, когда зависимость недоступна?

## 16. Безопасность как образ жизни

Безопасность нельзя добавить перед релизом. Она должна быть встроена в модель доступа, данные, инфраструктуру и процессы.

### Authentication vs Authorization — разные вещи

> Паспорт подтверждает, кто ты. Билет подтверждает, куда тебе можно войти. Одно не заменяет другое.

**Authentication** (AuthN) отвечает на вопрос «кто это?». **Authorization** (AuthZ) — «что ему можно?». Путаница опасна: пользователь может быть корректно залогинен и всё равно не иметь права читать чужой invoice.

**RBAC** выдаёт права через роли. **ABAC** учитывает атрибуты: владельца ресурса, tenant, регион, состояние объекта. Session-based auth проще ревокировать, **JWT** проще проверять без базы, но сложнее отзывать. Выбор зависит от угроз и lifecycle.

_Diagram: Запрос проходит два разных шага: authentication («кто ты?» — паспорт) и authorization («что тебе можно?» — билет). Залогинен — ещё не значит, что можно._

#### Authentication vs Authorization (AuthN / AuthZ)

- **Проблема:** «Пользователь залогинен» путают с «пользователю можно» — и он читает чужие данные.
- **Идея:** Два отдельных шага: AuthN устанавливает личность, AuthZ проверяет право на конкретный ресурс.
- **Пример:** Залогиненный клиент запрашивает invoice #42 другого клиента — AuthZ должна ответить 403.
- **Цена:** Выбор модели: RBAC проще, ABAC точнее; sessions легко отозвать, JWT легко проверить, но трудно отозвать.
- **Когда брать:** В любой системе, где у данных есть владелец.
- **Связи:** Один из слоёв **defense in depth**; угрозы spoofing и elevation of privilege из **STRIDE**.

### Threat Modeling — это профессиональная паранойя

> Хороший архитектор думает как злоумышленник не потому, что не доверяет людям, а потому что доверяет реальности.

**Threat modeling** — систематический поиск угроз до атаки. **STRIDE** помогает их искать: spoofing, tampering, repudiation, information disclosure, denial of service, elevation of privilege. **Defense in depth** означает несколько слоёв защиты: input validation, authz, encryption, audit log, rate limiting, least privilege.

**Secrets management** — не «положить ключ в env и забыть». Нужно понимать rotation, доступы, audit, blast radius и что произойдёт при утечке.

_Diagram: Слева — шесть классов угроз STRIDE, по которым проходишь каждый компонент. Справа — защита слоями: если один слой пробит, остаются другие._

#### Threat Modeling (STRIDE, defense in depth)

- **Проблема:** Безопасность вспоминают перед релизом, когда менять модель доступа поздно.
- **Идея:** Пройти компонент по STRIDE и поставить несколько слоёв защиты, а не один «главный» замок.
- **Пример:** Утечка ключа: что он открывает (blast radius), как быстро его ротировать, где это видно в audit.
- **Цена:** Время на разбор и дисциплина в secrets management.
- **Когда брать:** На этапе дизайна каждого нового компонента и интеграции.
- **Связи:** **AuthN vs AuthZ** — слой защиты; **observability** и audit log — чтобы заметить атаку.

> **Ключевой вопрос:** Что сможет сделать злоумышленник, если получит доступ к этому компоненту?

## 17. Наблюдаемость и операции

Нельзя чинить то, чего не видно. Система должна объяснять своё состояние без археологии в коде.

### Observability — monitoring говорит, что плохо, observability помогает понять почему

> Лампочка «check engine» полезна, но механику нужны ещё датчики, история и инструменты диагностики.

**Monitoring** отвечает «что-то не так». **Observability** — «почему». Три столпа observability: **logs**, **metrics**, **traces**. Structured logging делает логи queryable. Metrics показывают агрегаты. **Distributed tracing** связывает путь запроса через сервисы.

**Correlation ID** — маленькая вещь, которая спасает ночи: один request id проходит через gateway, service, queue, worker и downstream.

_Diagram: Три столпа — логи, метрики, трейсы. Один correlation ID проходит через все звенья, и путь запроса можно собрать целиком._

#### Observability (logs · metrics · traces, correlation ID)

- **Проблема:** Ночью что-то сломалось, а причину ищут археологией по коду.
- **Идея:** Система сама объясняет состояние: структурные логи, метрики-агрегаты, трейсы пути запроса.
- **Пример:** По request id `req-7f3a` находишь запрос в gateway, очереди и worker — и видишь, где он застрял.
- **Цена:** Инструменты, хранение данных и дисциплина прокидывать ID везде.
- **Когда брать:** С первого дня, особенно в распределённой системе и с очередями.
- **Связи:** Источник данных для **SLI** и **Symptom-based Alerting**; без него **Profiling** вслепую.

### Symptom-based Alerting — алертить нужно на симптомы

> Пользователю всё равно, что CPU 92%. Ему важно, что checkout не работает.

Хороший alert говорит о пользовательской боли — это **symptom-based alerting**: error rate, latency, failed payments, stale data. Плохой alert говорит о причине, которая может быть нормальной. Если алерты шумят, команда перестаёт им верить.

**Runbook** отвечает на вопрос «что делать в 03:00». **Post-mortem** отвечает «как мы сделаем, чтобы это не повторилось». Без обвинений (**blameless**); цель — улучшить систему, а не найти виновного.

_Diagram: Причины вроде CPU часто бывают нормой и дают шум. Алерт строят на симптомах боли пользователя, дальше — runbook и blameless post-mortem._

#### Symptom-based Alerting (runbook, blameless post-mortem)

- **Проблема:** Алерты шумят на причины, команда к ним привыкла и пропускает настоящий сбой.
- **Идея:** Будить человека только при боли пользователя; на каждый алерт — runbook.
- **Пример:** Не «CPU 92%», а «failed payments выросли» — и runbook: что проверить первым.
- **Цена:** Надо знать свои симптомы и поддерживать runbooks в актуальном виде.
- **Когда брать:** Для всего, что дежурный должен чинить ночью.
- **Связи:** Симптомы — это **SLI**; post-mortem — та же письменная культура, что **ADR** и **RFC**.

> **Ключевой вопрос:** Если это сломается ночью, какие данные помогут найти причину за 10 минут?

## 18. Документация, которая живёт

Незаписанное архитектурное решение исчезает вместе с контекстом автора.

### ADR — Architecture Decision Record лучше памяти

> Устная договорённость хороша до первого отпуска, увольнения или спора через полгода.

**Architecture Decision Record** фиксирует контекст, решение, альтернативы и последствия. ADR не должен быть романом. Хороший ADR отвечает: какую проблему решали, что выбрали, почему не выбрали другое, когда пересмотреть.

Документация нужна не для аудита, а для будущего изменения. Новый инженер должен понять не только «как», но и «почему».

_Diagram: Один ADR — одно решение: контекст, выбор, альтернативы, последствия и когда пересмотреть. Через полгода новый человек узнаёт «почему»._

#### ADR (Architecture Decision Record)

- **Проблема:** Решение жило в голове автора; автор ушёл, и никто не знает, почему сделано именно так.
- **Идея:** Короткая запись на одно решение: контекст, решение, альтернативы, последствия.
- **Пример:** «Берём PostgreSQL, а не MongoDB: нужны транзакции; пересмотреть, если появятся документные нагрузки».
- **Цена:** Полчаса на запись. Дешевле, чем спор через полгода.
- **Когда брать:** Для решений, которые дорого отменить.
- **Связи:** Фиксирует **Trade-offs** и долг; рядом с **RFC**; часть **Learning in Public**.

### C4 Model — диаграмма как рабочий инструмент, не украшение

> Карта метро не показывает провода и болты. Она показывает линии и пересадки. Этого достаточно, чтобы не заблудиться.

**C4 model** даёт четыре уровня: **Context**, **Container**, **Component**, **Code**. Обычно хватает первых трёх. **Sequence diagram** полезна, когда важен порядок взаимодействия. UML целиком редко нужен; отдельные диаграммы — да.

**Living documentation** живёт рядом с кодом, обновляется в PR и проверяется ревью. Документ в заброшенной wiki быстро становится исторической фантастикой.

_Diagram: Четыре уровня приближения C4 — обычно хватает трёх. Живая документация лежит рядом с кодом; забытая wiki превращается в фантастику._

#### C4 Model (living documentation)

- **Проблема:** Диаграммы рисуют для красоты: всё на одной картинке, и через месяц она врёт.
- **Идея:** Рисовать по уровням приближения: Context → Container → Component (→ Code, редко).
- **Пример:** Context: система, пользователи, внешние сервисы. Container: веб, API, база, очередь.
- **Цена:** Диаграммы надо обновлять в том же PR, что и код.
- **Когда брать:** Когда систему нужно объяснить новому человеку или другой команде.
- **Связи:** Показывает **Bounded Context** и границы; sequence diagram — для порядка вызовов.

> **Ключевой вопрос:** Сможет ли новый человек через полгода понять, почему мы сделали именно так?

## 19. Коммуникация и убеждение

Архитектор говорит с инженерами, продактом, бизнесом, безопасностью и юристами. Каждая аудитория слышит разный язык.

### Risk Translation — переводить риск на язык аудитории

> Врач не говорит пациенту только латинские названия. Он объясняет, что будет болеть, сколько лечить и что нельзя делать.

Это практика **перевода риска**. Инженеру можно сказать: «у нас нет idempotency на payment callback». Бизнесу нужно сказать: «при повторе webhook мы можем дважды списать или дважды выдать товар; это финансовый и репутационный риск».

**Stakeholder mapping** помогает понять, кому что важно: product хочет time-to-market, security — risk reduction, finance — predictable cost, support — понятное поведение, engineering — maintainability.

_Diagram: Один и тот же риск звучит по-разному для инженеров и для бизнеса. Карта стейкхолдеров показывает, что важно каждому._

#### Risk Translation (stakeholder mapping)

- **Проблема:** Технический риск звучит как жаргон, и бизнес его не слышит.
- **Идея:** Переводить риск в последствия, которые важны именно этой аудитории.
- **Пример:** «Нет idempotency на callback» → «можем дважды списать деньги — финансовый и репутационный риск».
- **Цена:** Нужно знать, что важно каждому стейкхолдеру, и говорить на его языке.
- **Когда брать:** Каждый раз, когда решение зависит от людей вне инженерии.
- **Связи:** Пример — **Idempotency**; бизнес-сторона — **NFR** и **cost of delay**.

### RFC — письменное предложение снижает температуру спора

> Спор у доски часто выигрывает самый громкий. Письменное предложение заставляет аргументы стоять отдельно от голоса.

**RFC** (Request for Comments) описывает проблему, ограничения, варианты, выбранное решение, риски и план rollout. Хороший RFC приглашает к критике до того, как решение стало политикой.

**Disagree and commit** работает только после честного обсуждения. Если команда не была услышана, это не commit, а подавление.

_Diagram: Разделы RFC и путь решения: черновик → ревью с критикой → решение → disagree and commit, но только если всех услышали._

#### RFC (Request for Comments, disagree and commit)

- **Проблема:** Спор у доски выигрывает самый громкий, а не самый правый.
- **Идея:** Письменно: проблема, ограничения, варианты, решение, риски, rollout. Критика — до решения.
- **Пример:** Перед переходом на новую очередь — RFC, неделя комментариев, затем решение и ADR.
- **Цена:** Медленнее, чем «решить на созвоне»; нужен владелец, который доведёт до решения.
- **Когда брать:** Для решений, которые затрагивают несколько команд или дорого отменить.
- **Связи:** Итог фиксирует **ADR**; инструмент **Influence without Authority**.

> **Ключевой вопрос:** Как объяснить это решение человеку, который не разделяет мои технические приоритеты?

## 20. Лидерство без власти

Архитектор часто остаётся individual contributor. Его власть — ясность мышления, доверие и способность делать команду сильнее.

### Influence without Authority — влияние без формальной власти

> Дирижёр не играет на каждом инструменте, но без него оркестр быстро превращается в набор талантливых людей, играющих разное произведение.

Это понятие **influence without authority**. Архитектор не должен становиться bottleneck на каждое решение. Его задача — задать принципы, объяснить границы, вырастить людей и вмешиваться там, где цена ошибки высока.

**Mentoring** архитектора — это не «делай как я». Это обучение вопросам: какие альтернативы ты видел, что потерял, как протестируешь риск, где граница ответственности.

_Diagram: Слева — архитектор как узкое горлышко: все решения ждут в очереди. Справа — множитель: принципы, границы и вопросы, а решают команды._

#### Influence without Authority (влияние без власти, mentoring)

- **Проблема:** Архитектор решает всё сам и становится очередью для всех команд.
- **Идея:** Влиять принципами, границами и вопросами, а не приказами.
- **Пример:** Вместо «делай так» — «какие альтернативы ты видел и как протестируешь риск?»
- **Цена:** Медленнее в моменте; нужно доверие, которое строится годами.
- **Когда брать:** Всегда, когда у тебя нет прямых подчинённых, а решения нужны.
- **Связи:** Работает через **RFC** и **ADR**; противоположность — **Ivory Tower Architect**.

### Delegation with Guardrails — делегировать не значит снять ответственность

> Капитан может доверить штурвал, но не может сказать, что курс корабля теперь не его проблема.

Часть архитектурных решений должна приниматься командами. Иначе архитектор становится очередью. Но должны быть **guardrails**: принципы, review, ADR, platform constraints, quality gates.

Архитектор вмешивается, когда решение необратимо, ломает системные инварианты, создаёт security risk или влияет на несколько команд.

_Diagram: Команда решает сама внутри ограждений. Архитектор вмешивается только по четырём сигналам справа._

#### Delegation with Guardrails (делегирование с ограждениями)

- **Проблема:** Либо всё через архитектора (очередь), либо никто не отвечает за курс.
- **Идея:** Команды решают сами внутри guardrails; архитектор отвечает за курс и вмешивается по чётким сигналам.
- **Пример:** Библиотеку логов команда выбирает сама; смену модели tenancy — только с архитектором.
- **Цена:** Guardrails надо сформулировать, записать и проверять автоматически, где можно.
- **Когда брать:** Когда команд больше одной, а архитектор один.
- **Связи:** Сигнал «необратимо» — из **Reversible vs Irreversible**; guardrails — **ADR** и quality gates.

> **Ключевой вопрос:** Я усиливаю способность команды принимать решения или подменяю команду собой?

## 21. Бизнес и продукт

Архитектура имеет смысл только в контексте бизнес-цели. Иначе это дорогая инженерная эстетика.

### Non-functional Requirements — тоже бизнес-требования

> Для магазина «checkout работает в Black Friday» — не техническая деталь, а деньги.

**Non-functional requirements** (NFR): performance, availability, security, compliance, operability — это не «технические хотелки». Это свойства продукта. Архитектор переводит их в business impact: потерянная выручка, риск штрафа, стоимость поддержки, скорость запуска рынков.

**Cost of delay** помогает обсуждать не только стоимость работы, но и стоимость ожидания. Иногда архитектурная инвестиция без немедленного ROI нужна, потому что без неё следующие фичи будут дорожать.

_Diagram: Слева — нефункциональные требования, справа — то, во что они превращаются для бизнеса. Архитектор — переводчик посередине._

#### Non-functional Requirements (NFR, cost of delay)

- **Проблема:** Качество системы считают «технической хотелкой» и откладывают.
- **Идея:** NFR — свойства продукта; говорить о них через выручку, риск и стоимость.
- **Пример:** «Checkout выдерживает Black Friday» — это деньги, а не деталь.
- **Цена:** Нужно оценить влияние в цифрах, хотя бы грубо.
- **Когда брать:** Когда архитектурная работа конкурирует с фичами за время.
- **Связи:** В цифрах — **SLO**; отложенная работа — **Technical Debt**; язык — **Risk Translation**.

### Build vs Buy — не вопрос гордости

> Не каждая компания должна строить собственную электростанцию, чтобы включить свет.

**Build** даёт контроль и дифференциацию. **Buy** даёт скорость и снижает операционную нагрузку. **Vendor lock-in** — реальный риск, но сам по себе не аргумент против покупки. Вопрос: насколько дорого будет выйти, если поставщик изменит цену, API или качество?

Архитектор помогает продукту видеть **capability map**: какие способности являются ядром бизнеса, а какие лучше купить.

_Diagram: Строим ядро, за которое платят клиенты; покупаем типовое. Для покупки главный вопрос — цена выхода._

#### Build vs Buy (capability map, vendor lock-in)

- **Проблема:** Пишут своё из гордости или покупают всё подряд без плана выхода.
- **Идея:** Строить то, что отличает бизнес; покупать типовое. Для покупки — оценить цену выхода.
- **Пример:** Свой движок предметной логики — build; рассылка писем или платежи — обычно buy.
- **Цена:** Build — время и поддержка навсегда. Buy — зависимость от цены, API и качества поставщика.
- **Когда брать:** Перед каждым «давайте напишем своё».
- **Связи:** Ловушка **NIH syndrome**; изолировать поставщика помогает **Dependency Inversion**.

> **Ключевой вопрос:** Как это архитектурное решение меняет скорость, риск или стоимость бизнеса?

## 22. AI-native архитектор

Когда код пишут агенты, ценность архитектора смещается в спецификацию, архитектурное мышление и контроль качества.

### Specification-driven Development — spec quality становится bottleneck

> Если строительная бригада стала в десять раз быстрее, главным ограничением становится не скорость кирпичей, а качество чертежей.

AI-агенты ускоряют implementation, но не отменяют архитектуру. Плохо сформулированная задача просто быстрее превращается в плохой код. **Specification-driven development** означает, что основной артефакт — спецификация поведения, границ, инвариантов, тестов и acceptance criteria.

Архитектор в AI-native процессе пишет меньше низкоуровневого кода, но больше точной прозы. Он ревьюит diff, тесты, архитектурные границы и соответствие спецификации.

_Diagram: Спецификация — главный артефакт. Агент быстро превращает её в код, архитектор проверяет код против спецификации и при ошибке чинит спецификацию._

#### Specification-driven Development (spec как главный артефакт)

- **Проблема:** Агент пишет код в десять раз быстрее — и так же быстро строит не то.
- **Идея:** Главный артефакт — спецификация: поведение, границы, инварианты, тесты, acceptance criteria.
- **Пример:** Вместо «сделай оплату» — сценарии, ошибки, инвариант «одна оплата на заказ» и тесты к нему.
- **Цена:** Архитектор пишет больше точной прозы и меньше кода.
- **Когда брать:** Всегда, когда implementation делает AI-агент.
- **Связи:** Проверка — **Agent Output Review**; инварианты из **API Contract** и **Bounded Context**.

### Agent Output Review — код агента требует такой же дисциплины, как PR человека

> Быстрый джуниор, который пишет тысячу строк за час, всё равно нуждается в ревью. Скорость не делает код правильным.

Код от агента нельзя принимать потому, что он компилируется. Нужны tests, evals, import boundaries, type checks, security review. Особенно важны **scenario evaluations**: система должна проходить реальные кейсы, а не только happy path.

AI-native организация выигрывает не там, где «все вайбкодят», а там, где есть сильные спецификации, маленькие итерации, автоматические проверки и архитектурное владение.

_Diagram: PR агента проходит те же ворота качества, что и PR человека: тесты, сценарные evals, границы импортов, типы, security review._

#### Agent Output Review (quality gates для AI-кода)

- **Проблема:** Код агента принимают, потому что он компилируется и выглядит уверенно.
- **Идея:** Те же автоматические ворота качества и то же ревью, что для человека.
- **Пример:** Сценарные evals ловят, что агент обработал только happy path и забыл повтор платежа.
- **Цена:** Нужно заранее построить автоматические проверки и границы импортов.
- **Когда брать:** Каждый PR от агента, без исключений.
- **Связи:** Проверяет соответствие **Specification-driven Development**; границы — из **Dependency Inversion**.

> **Ключевой вопрос:** Достаточно ли точна спецификация, чтобы быстрый исполнитель не построил не то?

## 23. Антипаттерны архитектора

Архитектор может быть опасен именно потому, что звучит убедительно. Знание ловушек экономит годы.

### Ivory Tower Architect — архитектор в башне из слоновой кости

> Человек рисует идеальный город на холме, но никогда не спускается посмотреть, где люди реально ходят.

Это антипаттерн **ivory tower architect**: решения принимаются вдали от кода, эксплуатации и команды. Диаграммы красивы, но implementation страдает. Лекарство простое: читать PR, смотреть инциденты, разговаривать с инженерами, самому проходить путь изменения.

_Diagram: Башня далеко от земли: от кода, инцидентов и инженеров. Лекарство — спуститься: читать PR, смотреть инциденты, говорить, проходить путь изменения._

#### Ivory Tower Architect (архитектор в башне)

- **Признак:** Красивые диаграммы, которые команда не может реализовать.
- **Почему вредно:** Решения не учитывают реальный код, эксплуатацию и людей.
- **Лекарство:** Читать PR, смотреть инциденты, разговаривать с инженерами, самому проходить путь изменения.
- **Связи:** Противоположность **Influence without Authority**; про форму, а не реальность — **Cargo Cult**.

### Resume-driven Development и Cargo Cult

> Покупать пожарную машину потому, что она впечатляет соседей, странно, если у тебя нет воды и пожарных.

**Resume-driven development** выбирает технологии ради строки в CV. **Cargo cult engineering** копирует форму чужого решения без причины. **NIH syndrome** (Not Invented Here) заставляет писать своё там, где зрелый внешний инструмент лучше.

Ещё одна ловушка — **technical perfectionism**. Идеальная архитектура, которая не доехала до пользователя, проигрывает достаточно хорошей системе, которая работает и может эволюционировать.

_Diagram: Четыре ловушки уводят от настоящей проблемы: технологии ради резюме, копирование формы, «напишем своё» и вечная полировка._

#### Resume-driven Development (cargo cult, NIH, perfectionism)

- **Признак:** Решение объясняют модой, чужим примером или красотой, а не проблемой.
- **Почему вредно:** Платишь цену сложной технологии, не получая выгоды; или не доезжаешь до пользователя.
- **Пример:** Kubernetes и микросервисы для команды из трёх человек, «потому что так у Netflix».
- **Лекарство:** Начинать с проблемы и честно называть цену каждого варианта.
- **Связи:** Лечится **Trade-offs** и **Build vs Buy**; часто рождает **Distributed Monolith**.

> **Ключевой вопрос:** Я выбираю это решение ради проблемы или ради ощущения архитектурной красоты?

## 24. Постоянный рост

Архитектура — бесконечная игра. Технологии меняются, но способность задавать правильные вопросы должна только усиливаться.

### T-shaped / M-shaped Skills — учиться по системам, не по хайпу

> Повар растёт не от просмотра рекламы ножей, а от понимания продуктов, тепла, времени и вкуса.

Новые технологии стоит изучать через вопросы: какую проблему они решают, какую цену вводят, где уже провалились, какие альтернативы есть, что должно быть правдой, чтобы они стали полезны.

_Diagram: Пять вопросов-фильтров для любой новой технологии. Пройдя их, решаешь: брать сейчас или подождать._

**T-shaped skills** дают глубину в одной области и ширину по соседним. **M-shaped skills** появляются у зрелого архитектора: несколько глубоких опор — данные, распределённость, безопасность, продукт, AI-инструменты.

_Diagram: T — одна глубокая область плюс ширина. M — несколько глубоких опор у зрелого архитектора._

#### T-shaped / M-shaped Skills (учиться по системам, не по хайпу)

- **Проблема:** Учат каждую модную технологию, а глубины и суждения не прибавляется.
- **Идея:** Изучать технологии через вопросы о проблеме и цене; растить несколько глубоких опор.
- **Пример:** Новая база: какую проблему решает, где уже провалилась, что должно быть правдой, чтобы она помогла нам.
- **Цена:** Медленнее, чем читать анонсы; глубина требует лет.
- **Когда брать:** При каждой новой технологии на радаре.
- **Связи:** Защита от **Resume-driven Development**; опоры — темы этого курса.

### Learning in Public — ускоряет зрелость

> Когда объясняешь решение письменно, дырки в мышлении становятся видны раньше, чем в продакшене.

**Learning in public** — учиться открыто, письменно. Пиши ADR, RFC, engineering notes, post-mortems, короткие разборы решений. Учись у архитекторов сильнее тебя: не только что они выбрали, но как они рассуждали.

Архитектор, которому подражают, обычно не тот, кто знает больше всех терминов. Это человек, рядом с которым команда начинает задавать лучшие вопросы.

_Diagram: Цикл: решаешь → записываешь → получаешь обратную связь → задаёшь лучшие вопросы. Дырки в мышлении видны раньше продакшена._

#### Learning in Public (учиться письменно и открыто)

- **Проблема:** Ошибки в рассуждении находит продакшен, а не коллеги.
- **Идея:** Записывать решения и разборы, показывать их и учиться на обратной связи.
- **Пример:** ADR, RFC, engineering notes, post-mortems, короткие разборы решений.
- **Цена:** Время на письмо и смелость показать незаконченное мышление.
- **Когда брать:** Постоянно — это и есть рост архитектора.
- **Связи:** Использует **ADR**, **RFC** и **post-mortem**; делает команду сильнее, как **Influence without Authority**.

> **Последний вопрос:** Какие вопросы я теперь задаю раньше, чем открываю редактор?

#### Финальная самопроверка

- Я могу назвать trade-offs решения без защиты эго.
- Я понимаю, где в системе живёт источник правды.
- Я различаю обратимые и необратимые решения.
- Я могу объяснить архитектуру инженеру, продукту и бизнесу разными словами.
- Я пишу решения так, чтобы через год их можно было понять.
- Я не прячу сложность за словами «best practice».

### Карта курса: как всё связано

> Карта метро в конце поездки: теперь видно, как линии пересекаются.

Мышление выбирает форму системы, данные и качество. Структура записывается в документы, качество проверяется безопасностью и эксплуатацией, а документы и риски убеждают бизнес. Всё вместе масштабируется в AI-native работу и личный рост.

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

## Шпаргалка: все 52 понятия курса

### Мышление архитектора (1–4)

- **Long-term Thinking** (думать годами): Сначала проверить, правильно ли поставлена задача, и как решение будет жить через три года.
- **Reversible vs Irreversible** (обратимые и необратимые решения): Быстро решать то, что легко отменить; медленно — то, что меняет траекторию системы.
- **Trade-offs** (осознанный обмен): Каждый выбор покупает одно свойство ценой другого. Best practice без контекста — плохой совет.
- **Over- / Under-engineering** (сложность как налог): Сложность оправдана, только если покупает важное свойство. Держать середину.
- **Technical Debt** (технический долг): Решение, которое ускоряет сейчас и дорожает потом. Кредит, а не мусор.
- **Debt Interest** (проценты по долгу): Замедление каждого следующего изменения. Долг в горячей зоне дороже всего.
- **Cognitive Load** (когнитивная нагрузка): Сколько контекста нужно, чтобы безопасно менять компонент. Убирать случайную сложность.
- **Conway's Law** (закон Конвея): Система повторяет структуру коммуникаций организации.

### Структура системы (5–7, 11)

- **Cohesion & Coupling** (связность и сцепление): Внутри компонента — про одно; снаружи — знать о других как можно меньше.
- **Bounded Context** (ограниченный контекст): Граница, внутри которой слова имеют один смысл.
- **Dependency Inversion** (зависимости к центру): Бизнес-логика зависит от абстракций; детали подключаются снаружи (ports and adapters).
- **Abstraction** (абстракция ради изменений): Слой нужен, чтобы поглощать изменения и тестироваться без внешнего мира, а не для красоты.
- **API Contract** (контракт важнее транспорта): Схема, ошибки, версии и совместимость важнее выбора REST, GraphQL или gRPC.
- **Idempotency** (идемпотентность): Повтор операции даёт тот же итоговый эффект. Защита от retries и дублей.
- **Modular Monolith** (модульный монолит): Одно приложение со строгими внутренними границами. Часто лучший старт.
- **Distributed Monolith** (распределённый монолит): Сервисы, которые релизятся только вместе. Цена распределённости без независимости.
- **Strangler Fig** (миграция по кусочкам): Новая система растёт вокруг старой и постепенно забирает трафик, вместо переписывания с нуля.

### Данные и распределённость (8–10, 12)

- **Data Model** (данные живут дольше кода): Самое дорогое решение: нормализация, OLTP против OLAP.
- **Event Sourcing** (журнал событий — источник правды): Состояние собирается из событий: вся история и аудит, но дорого в поддержке и развитии.
- **CQRS** (раздельные модели записи и чтения): У команд и запросов свои модели; полезно, когда чтение и запись сильно различаются.
- **Single Source of Truth** (единый источник правды): Для каждого факта известно, где его главная версия; остальное — производные копии.
- **Cache Invalidation** (кэш как вторая правда): Скорость ценой свежести; главный вопрос — когда инвалидировать.
- **Optimistic vs Pessimistic Locking** (проверка при записи или блокировка заранее): Два способа не дать параллельным правкам затереть друг друга.
- **CAP / PACELC** (сеть — источник неопределённости): При разрыве сети — consistency или availability; без разрыва — latency или consistency.
- **Consistency Models** (strong, eventual, causal): Не самая строгая модель, а достаточная для риска.
- **Saga** (цепочка шагов с компенсациями): Длинная транзакция через несколько сервисов, где у каждого шага есть отмена вместо общей блокировки.
- **Queue vs Pub/Sub** (очередь — не просто «потом»): Async развязывает во времени, но приносит задержки, дубли и порядок.
- **At-least-once Delivery** (exactly-once — маркетинг): Сообщение может прийти дважды; потребитель должен быть идемпотентным. DLQ, backpressure.

### Качество системы (13–15)

- **Tail Latency** (p95 / p99): Пользователь чувствует хвост, а не среднее.
- **Profiling** (сначала измерь): Оптимизировать только найденную горячую точку; Amdahl и Little задают пределы.
- **Vertical vs Horizontal Scaling** (scale up / scale out): Одна большая машина или много одинаковых за балансировщиком.
- **Scale Cube** (X / Y / Z): Клонировать, делить по функциям, делить по данным.
- **Retry + Circuit Breaker + Bulkhead** (устойчивость к сбоям): Повторы с backoff и jitter, размыкатель для мёртвых зависимостей, изоляция пулов.
- **SLI / SLO / SLA** (error budget): Измерение, цель и обещание; бюджет ошибок решает, фичи или надёжность.

### Безопасность и эксплуатация (16–17)

- **Authentication vs Authorization** (AuthN / AuthZ): «Кто ты?» и «что тебе можно?» — два разных шага.
- **Threat Modeling** (STRIDE, defense in depth): Искать угрозы до атаки и защищаться слоями.
- **Observability** (logs · metrics · traces): Система объясняет «почему»; correlation ID связывает весь путь.
- **Symptom-based Alerting** (runbook, post-mortem): Алерт — на боль пользователя; runbook — что делать; post-mortem — без обвинений.

### Документы и коммуникация (18–19)

- **ADR** (Architecture Decision Record): Контекст, решение, альтернативы, последствия — на одно решение.
- **C4 Model** (living documentation): Диаграммы по уровням приближения, живущие рядом с кодом.
- **Risk Translation** (stakeholder mapping): Один риск — разные слова для инженеров и бизнеса.
- **RFC** (disagree and commit): Письменное предложение и критика до решения.

### Лидерство и бизнес (20–21)

- **Influence without Authority** (влияние без власти): Принципы, границы и вопросы вместо приказов.
- **Delegation with Guardrails** (делегирование с ограждениями): Команды решают сами; архитектор вмешивается при необратимости, инвариантах, security и многих командах.
- **Non-functional Requirements** (NFR, cost of delay): Свойства продукта, выраженные в выручке, риске и стоимости.
- **Build vs Buy** (capability map): Строить ядро, покупать типовое, знать цену выхода.

### AI-native, ловушки и рост (22–24)

- **Specification-driven Development** (spec как артефакт): Чем быстрее исполнитель, тем важнее точность спецификации.
- **Agent Output Review** (quality gates): Код агента проходит те же проверки, что и PR человека.
- **Ivory Tower Architect** (архитектор в башне): Решения вдали от кода, эксплуатации и команды.
- **Resume-driven Development** (cargo cult, NIH, perfectionism): Технологии ради резюме, копия формы, своё вместо зрелого, вечная полировка.
- **T-shaped / M-shaped Skills** (учиться по системам): Глубина плюс ширина; у зрелого архитектора — несколько глубоких опор.
- **Learning in Public** (учиться письменно): Записывать решения — и видеть дырки в мышлении раньше продакшена.

> Архитектор — это инженер, который научился видеть последствия раньше, чем они стали инцидентом.

Конец курса · 24 модуля · дальше начинается практика.

Перечитай этот курс не как справочник, а как набор вопросов. Архитектура начинается там, где ты
останавливаешься перед решением и честно называешь цену каждого варианта.
