Архитектурный выбор — это не следование трендам индустрии, а поиск баланса между инженерными компромиссами. Представление о том, что любая система обязана пройти путь от классического монолита к микросервисам, технически некорректно: каждый подход решает свой класс задач и накладывает специфические ограничения на разработку, эксплуатацию и бизнес-процессы.
Анатомия подходов: что скрывается под терминами
Классический монолит
Классический монолит представляет собой систему, в которой вся бизнес-логика скомпонована в единый исполняемый артефакт (deployable unit), исполняется в общем процессе операционной системы и, как правило, использует единую базу данных.
Главное свойство классического монолита — минимальная стоимость межкомпонентных вызовов (вызовы функций в памяти) и простота сквозных ACID-транзакций. Однако при отсутствии строгой архитектурной дисциплины монолит со временем рискует деградировать в сильно связанный код, где изменения в одном модуле непредсказуемо влияют на функциональность другого.
Модульный монолит (Modular Monolith)
Модульный монолит сохраняет ключевое эксплуатационное свойство классического монолита — сборку и развертывание в виде единого процесса. Принципиальное отличие заключается во внутренней организации кодовой базы:
- функциональность разделена на логические модули в соответствии с ограниченными контекстами (Bounded Contexts);
- взаимодействие между модулями происходит строго через публичные интерфейсы (API модуля) или внутреннюю шину событий в памяти;
- модули не имеют прямого доступа к внутренним структурам данных и таблицам базы данных друг друга (логическое разделение схем или изоляция на уровне сущностей);
- архитектурные правила и запреты нежелательных связей верифицируются на этапе сборки с помощью линтеров или тестов структуры кода.
Этот подход обеспечивает изоляцию компонентов без необходимости оплачивать накладные расходы распределенной инфраструктуры.
Микросервисная архитектура
Микросервисная архитектура — это распределенная система, состоящая из независимых автономных сервисов, каждый из которых:
- решает узкую задачу вокруг бизнес-возможности (business capability);
- владеет собственным изолированным хранилищем данных (паттерн Database-per-Service);
- развертывается и масштабируется независимо от остальной системы;
- взаимодействует с другими сервисами по сети через синхронные (gRPC, HTTP/REST) или асинхронные протоколы (брокеры сообщений).
Автономия сервисов приобретается ценой сетевых задержек, усложнения оркестрации и необходимости решать задачи распределенной согласованности данных.
Сравнение вариантов по ключевым осям принятия решений
Классический монолит --> Единый артефакт, общая БД, внутрипроцессные вызовы
Модульный монолит --> Единый артефакт, строгие границы доменов, изоляция данных
Микросервисы --> Множество артефактов, БД на сервис, сетевое взаимодействие (RPC/Event-driven)
Границы домена и связанность (Coupling & Domain Boundaries)
Степень понимания предметной области — определяющий фактор при выборе архитектуры.
- Классический монолит прощает неточности в границах домена на начальных этапах: рефакторинг кода и перенос логики внутри одного репозитория выполняются базовыми средствами среды разработки.
- Модульный монолит требует осознанного выделения модулей, но позволяет скорректировать ошибочно проведенные границы без дорогостоящей миграции сетевых API и разделения баз данных.
- Микросервисы требуют устойчивой доменной модели. Если границы проведены неверно, система превращается в «распределенный монолит»: любые изменения требуют одновременного развертывания нескольких сервисов, а сетевые вызовы между ними становятся избыточно частыми (chatty I/O).
Структура и масштаб инженерной команды (Закон Конвея)
Организационная структура напрямую отражается на архитектуре программной системы:
- 1–3 команды (до 15–20 инженеров): Классический или модульный монолит обеспечивает максимальную скорость поставки (Time-to-Market). Команда работает в едином контексте без накладных расходов на согласование распределенных контрактов и версионирование внешних API.
- Несколько параллельных стримов разработки: Модульный монолит позволяет закрепить ответственность за модулями (Code Ownership) за отдельными группами разработчиков в рамках одного репозитория.
- Множество независимых продуктовых команд (от 30–50+ инженеров): Микросервисы становятся оправданными, когда координация единого релиза превращается в узкое место. Команды получают возможность независимо разрабатывать, тестировать и развертывать свои сервисы.
Профиль нагрузки и масштабирование (Scalability)
- Монолит и модульный монолит масштабируются путем репликации всего приложения за балансировщиком нагрузки. Это практично и экономично, если профиль нагрузки распределен по системе относительно равномерно. Однако если одна ресурсоемкая операция требует специфического оборудования (например, GPU для вычислений или большой объем RAM), масштабировать придется весь монолит.
- Микросервисы позволяют точечно выделять вычислительные мощности под узкие места системы. Платой за это выступают сетевые накладные расходы: каждый межсервисный вызов добавляет задержку на передачу данных по сети, сериализацию и десериализацию payload.
Эксплуатация, надежность и наблюдаемость (Operations & Observability)
Сложность поддержки распределенной системы возрастает нелинейно:
- Монолитные системы: Локальное окружение запускается одной командой. Отладка выполняется стандартными инструментами IDE в едином процессе. Мониторинг сосредоточен вокруг сбора логов и метрик базового процесса и базы данных.
- Микросервисы: Требуют зрелой платформенной инфраструктуры: Service Discovery, распределенной трассировки (Distributed Tracing), централизованного логирования, инструментов управления сетевыми сбоями (Circuit Breaker, Retries). Сбой сети между сервисами переходит в категорию штатных ситуаций, которые программный код обязан обрабатывать непрерывно.
Целостность данных и транзакционная модель
- Монолитные архитектуры: Обеспечивают строгую согласованность данных (ACID) благодаря встроенным механизмам реляционных СУБД. Консистентность поддерживается на уровне единой транзакции.
- Микросервисы: Принцип изоляции данных исключает простые транзакции между сервисами. Система опирается на модель согласованности в конечном счете (Eventual Consistency). Для реализации сквозных бизнес-транзакций требуется внедрение сложных паттернов: Saga (оркестрация или хореография), Transactional Outbox и идемпотентных обработчиков сообщений.
Сводная матрица критериев выбора
| Параметр | Классический монолит | Модульный монолит | Микросервисы |
|---|---|---|---|
| Сложность развертывания | Низкая (1 артефакт) | Низкая (1 артефакт) | Высокая (множество артефактов) |
| Изоляция сбоев | Низкая (сбой процесса затрагивает всю систему) | Средняя (внутрипроцессная изоляция ошибок) | Высокая (деградация локализована в рамках сервиса) |
| Сетевые накладные расходы | Отсутствуют (вызовы в памяти) | Отсутствуют (вызовы в памяти) | Заметные (сетевой I/O, сериализация) |
| Сложность транзакций | Низкая (локальный ACID) | Низкая/Средняя (ACID или внутренние события) | Высокая (Eventual Consistency, Saga) |
| Размер команды | 1–3 команды | До 5–8 команд при четких зонах ответственности | Неограниченно при высокой автономии команд |
| Цена архитектурной ошибки | Низкая (быстрый рефакторинг) | Средняя (перенос модулей в коде) | Высокая (миграция распределенных БД и API) |
| Требования к платформе/DevOps | Базовые | Базовые / Средние | Высокие (K8s, трассировка, Service Mesh) |
Дерево решений: пошаговый алгоритм выбора
Чтобы определить подходящую архитектуру, последовательно сопоставьте параметры проекта:
[Старт: Проектирование архитектуры]
│
▼
1. Границы предметной области стабильны и четко формализованы?
├─► [НЕТ] ──► МОДУЛЬНЫЙ МОНОЛИТ (сохраняет гибкость для рефакторинга)
│
▼ [ДА]
2. Над проектом работает более 4–5 независимых инженерных команд?
├─► [НЕТ] ──► МОДУЛЬНЫЙ МОНОЛИТ или КЛАССИЧЕСКИЙ МОНОЛИТ
│
▼ [ДА]
3. Есть ли выраженная асимметрия нагрузки или необходимость в изолированном деплое узлов?
├─► [НЕТ] ──► МОДУЛЬНЫЙ МОНОЛИТ с разделением зон ответственности
│
▼ [ДА]
4. В организации развернута зрелая DevOps-платформа (трассировка, CI/CD, оркестрация)?
├─► [НЕТ] ──► МОДУЛЬНЫЙ МОНОЛИТ (приоритет — развитие инфраструктуры)
│
▼ [ДА]
ИТОГ: МИКРОСЕРВИСНАЯ АРХИТЕКТУРА
- Определенность домена: Если бизнес-модель проходит валидацию или часто меняется (MVP, ранние стадии продукта) — распределенная архитектура создает избыточное трение.
- Размер штата: При работе до 20–30 инженеров затраты на поддержку межсервисной инфраструктуры перекрывают выгоду от раздельного развертывания.
- Асимметрия нагрузки: Микросервисы дают результат, когда отдельным компонентам требуются принципиально разные вычислительные профили, жестко изолированные SLA или независимые релизные циклы.
- Инфраструктурная зрелость: Без автоматизированного тестирования, сквозного мониторинга и отлаженных процессов поставки переход к микросервисам приводит к потере контроля над системой.
Фиксация архитектурного выбора: шаблон записи ADR
Архитектурные решения рекомендуется документировать с помощью Architecture Decision Record (ADR) — лаконичного документа, фиксирующего контекст, принятые решения и компромиссы непосредственно в репозитории проекта.
Пример заполненного ADR
# ADR-001: Выбор базовой архитектуры платежного шлюза
## Статус
Принято (Accepted)
## Контекст
Проектируется новая система обработки платежей и управления счетами клиентов.
Вводные данные:
* Состав команды: 2 инженерные группы (всего 10 человек).
* Ожидаемая нагрузка: до 400 RPS в пиковые периоды, высокий процент транзакций записи.
* Доменная модель продолжает уточняться продуктовыми аналитиками.
* Выделенной платформенной команды нет, поддержка инфраструктуры лежит на продуктовых инженерах.
## Рассмотренные варианты
1. Микросервисная архитектура (сервисы платежей, счетов, уведомлений, аналитики).
2. Классический монолит.
3. Модульный монолит с изолированными доменными контекстами.
## Решение
Выбрать архитектуру **Модульного монолита**.
Кодовая база организуется в рамках одного репозитория с разделением на модули `Payment`, `Billing`, `Notifications`. Связи между модулями реализуются исключительно через публичные интерфейсы и внутренние события в памяти. Прямой доступ к таблицам чужих модулей запрещен правилами статического анализа.
## Последствия
### Положительные:
* Сохранение транзакционной целостности (ACID) без усложнения распределенными протоколами.
* Отсутствие сетевых задержек между компонентами.
* Простая и воспроизводимая локальная среда разработки.
* Низкая стоимость реорганизации доменных границ при изменении требований.
### Риски и ограничения:
* Общий runtime: аварийный сбой процесса останавливает все модули.
* Требуется постоянный автоматизированный контроль за архитектурными зависимостями в кодовой базе.
Часто задаваемые вопросы (FAQ)
Можно ли начать с монолита и затем перейти на микросервисы?
Да, если изначально проектировать систему как модульный монолит. Ключевые условия для последующего выделения сервисов: отсутствие прямых зависимостей в обход публичных интерфейсов, отказ от перекрестных внешних ключей (Foreign Keys) между контекстами в базе данных и асинхронный обмен сообщениями между модулями.
Когда микросервисы становятся объективно необходимыми?
Микросервисы незаменимы, когда масштаб организации превышает порог эффективной координации в общем релизном цикле (десятки продуктовых команд), либо когда отдельные узлы системы имеют несовместимые требования к ресурсам, контурам безопасности (например, зона соответствия PCI DSS) или частоте релизов.
В чем ключевое отличие модульного монолита от слабоструктурированного монолита?
В жестком контроле внутренних архитектурных границ. В модульном монолите каждый компонент инкапсулирует свою внутреннюю логику и схемы данных. Попытки обратиться к приватным классам или напрямую выполнить SQL-запрос к таблицам другого модуля блокируются линтерами и тестами архитектуры еще на этапе сборки.
Как определить, что в проекте получился «распределенный монолит»?
Основные признаки распределенного монолита:
- сервисы невозможно обновить независимо (для релиза одного сервиса требуется синхронный деплой остальных);
- правка модели данных в одном сервисе вызывает каскадные изменения в соседних сервисах;
- несколько сервисов обращаются к одной и той же базе данных без разделения прав и схем;
- сбой одного второстепенного сервиса приводит к полному отказу всей системы.
Уступает ли модульный монолит микросервисам по производительности?
В типовых сценариях модульный монолит демонстрирует меньшие задержки (latency), поскольку обмен данными происходит в оперативной памяти без сетевого стека, сериализации JSON/Protobuf и накладных расходов TLS. Микросервисы получают преимущество только тогда, когда конкретную изолированную операцию требуется масштабировать на десятки специализированных серверов отдельно от остального кода.
Вывод
Архитектура системы — это прикладной инструмент достижения бизнес-целей и обеспечения продуктивности инженерных команд, а не показатель технологической зрелости:
- Классический монолит и модульный монолит остаются практичным и устойчивым выбором для большинства проектов, небольших и средних команд, а также для систем с развивающейся структурой домена.
- Модульный монолит сочетает дисциплину изолированных доменов и простоту эксплуатации единого артефакта.
- Микросервисы решают задачи организационной независимости масштабных команд и избирательного масштабирования, но требуют существенных затрат на платформенную инфраструктуру, надежность сети и согласованность данных.
Выбирайте архитектуру исходя из реальных ограничений команды и требований к системе, обязательно фиксируя контекст и последствия в архитектурных записях (ADR).
Источники
- Decomposing monoliths into microservices
- REL03-BP01 Choose how to segment your workload
- Architectures monolithiques et microservice - Training
- Architecting generative AI applications for production - AWS ...
- docs.aws.amazon.com › wellarchitected › latestREL03-BP01 Choose how to segment your workload
- CI/CD for Microservices - Azure Architecture Center



.svg.webp)





