Микросервисы vs монолит: когда действительно делить систему
Монолит подходит для MVP и небольших команд дольше, чем принято думать. Делить систему стоит, когда появляются измеримые сигналы — конфликты релизов, разная нагрузка на модули, разный жизненный цикл доменов. Модульный монолит — реалистичный средний путь для большинства проектов 2026 года.

Вопрос «микросервисы или монолит» почти всегда задают не вовремя. На старте проекта на него нельзя ответить осмысленно — границы доменов ещё не видны, нагрузка непредсказуема, а команда может состоять из двух человек. Делить систему имеет смысл не потому, что «так делают все крупные компании», а когда появляются конкретные, измеримые сигналы боли, которые монолит больше не снимает. Если заказчик делает сайт или веб-приложение с нуля, решение об архитектуре принимается именно на старте проекта: команда, которая берёт создание сайтов под ключ в YUSMP Group, закладывает модульную структуру заранее — чтобы потом можно было выделить отдельный сервис без полного переписывания системы.
Монолит и микросервисы — в чём разница на практике
Монолит — это приложение, которое разворачивается как единый процесс или набор идентичных процессов: весь код живёт в одном репозитории, собирается в один артефакт и масштабируется целиком. Микросервисы — это набор независимо развёртываемых сервисов, каждый со своей базой данных, своим циклом релиза и общением через сеть, а не через вызов функции внутри процесса. Разница не в количестве файлов и не в архитектурных слоях внутри кода, а именно в единице развёртывания: можно выкатить изменение одного домена, не трогая остальные, или нет.
Когда монолит — это правильный выбор, а не компромисс
Для большей части проектов монолит остаётся осознанным инженерным решением, а не временной мерой «пока не доросли»:
- Ранняя стадия продукта или MVP, когда границы доменов ещё не устоялись и любое разделение будет угадыванием
- Команда из одного-трёх разработчиков, где сетевые границы между сервисами добавляют координационные накладные расходы без выгоды
- Нагрузка предсказуема и равномерна по всей системе — нет модуля, который требует отдельного масштабирования под пиковый трафик
- Нет организационной необходимости в независимых релизах: все изменения всё равно согласуются и выкатываются одной командой
Модульный монолит — третий вариант, который обычно и нужен
Модульный монолит — это одно развёртываемое приложение, внутри которого код разбит на модули с явными границами и собственным внутренним API, как если бы это были будущие сервисы, только без сети между ними. Модуль Billing не обращается напрямую к таблицам модуля Orders, а вызывает его публичный интерфейс; переиспользование чужих внутренних структур данных запрещено на уровне код-ревью, а в идеале — и на уровне инструментов статического анализа.
Границы модулей обычно проводят по двум правилам: каждый модуль отвечает за один связный домен с собственной терминологией (bounded context в терминах DDD), и каждый модуль можно мысленно вынести в отдельный сервис, просто заменив прямой вызов функции на сетевой запрос, без изменения остальной архитектуры. Если провести эту границу заранее не получается, часто это сигнал, что домены пока недостаточно поняты — и торопиться с физическим разделением на отдельные сервисы точно не стоит.
Сравнение монолита, модульного монолита и микросервисов
Коротко — чем различаются три варианта по параметрам, которые реально влияют на решение:
| Параметр | Монолит | Модульный монолит | Микросервисы |
|---|---|---|---|
| Скорость разработки на старте | Высокая | Высокая, чуть ниже за счёт дисциплины границ | Низкая из-за инфраструктурной обвязки |
| Стоимость инфраструктуры | Низкая, один деплой | Низкая, один деплой | Высокая: оркестрация, service mesh, наблюдаемость |
| Независимое масштабирование | Нет | Нет на уровне процесса | Да, по каждому сервису отдельно |
| Отказоустойчивость | Падение модуля кладёт всё приложение | Риск тот же, но локализуется проще | Сбой изолирован в границах сервиса |
| Сложность эксплуатации | Низкая | Низкая | Высокая: распределённый мониторинг, трассировка |
| Порог для команды | Один-три разработчика | От одной команды | Отдельная команда на сервис или близко к этому |
Измеримые признаки, что систему пора делить
Разделение стоит рассматривать не по ощущению «монолит разросся», а по конкретным симптомам:
- Команды регулярно блокируют релизы друг друга — чужой незавершённый фрагмент кода задерживает выкатку вашего модуля
- Разные модули требуют принципиально разного масштабирования: один обслуживает тысячи запросов в секунду, другой — десятки в сутки
- Домены объективно нуждаются в разных технологических стеках — например, модулю аналитики нужен язык с другой экосистемой для ML-нагрузки
- Время полного цикла сборки и деплоя растёт месяц от месяца и начинает измеряться в десятках минут на каждое изменение
- Падение одного второстепенного модуля (например, генерации PDF-отчётов) кладёт весь процесс оформления заказа
- У доменов явно разный жизненный цикл: один меняется еженедельно под эксперименты, другой стабилен годами и трогать его страшно при каждом общем деплое
Признаки, что разделение было ошибкой
Микросервисы не бесплатны, и у преждевременного разделения есть собственный набор симптомов:
- Получился распределённый монолит: сервисы физически разнесены, но по-прежнему требуют совместного согласованного релиза, потому что жёстко связаны по контракту
- Простые внутрипроцессные вызовы функций превратились в сетевые запросы — с задержкой, сериализацией и дополнительной точкой отказа на каждом шаге
- Задержки (latency) заметно выросли из-за цепочки синхронных вызовов между сервисами вместо одного обращения внутри процесса
- Команда тратит больше времени на оркестрацию, мониторинг и отладку распределённых трассировок, чем на развитие продуктовых фич
Если в списке узнаётся собственная система, это не повод стыдиться решения — это нормальный сигнал пересмотреть границы, а иногда и консолидировать часть сервисов обратно.
Как перейти постепенно, не переписывая всё с нуля
Полное переписывание системы под микросервисы почти всегда переоценивает себя по срокам и риску. Практичнее работает паттерн «душитель» (strangler fig) — постепенная замена части монолита новым сервисом, пока старый код продолжает работать рядом:
- Выбрать первый кандидат на выделение — домен с самым чётким контуром и наименьшим числом скрытых зависимостей от остального кода
- Поставить прокси или фасад перед существующей функциональностью, через который в будущем пойдёт весь трафик к этому домену
- Перевести трафик на новый сервис постепенно, маршрутизируя по проценту запросов или по сегменту пользователей, а не всем разом
- Проверить поведение на фиче-флагах и параллельном сравнении ответов старого и нового пути, прежде чем делать переключение необратимым
- Вывести старый код из монолита только после того, как новый сервис отработал под реальной нагрузкой без регрессий достаточное время
Чек-лист перед выделением первого сервиса
Прежде чем резать монолит на части, стоит честно пройтись по списку:
- У домена есть собственная, отдельная от остальных база данных — или её реально завести без миграции общих таблиц
- Есть команда, которая возьмёт эксплуатацию, дежурство и мониторинг этого сервиса на себя без постоянной помощи соседей
- Контракт между сервисом и остальной системой описан явно — версионируемое API, а не прямой доступ к внутренним структурам
- Есть план, что делать при недоступности нового сервиса: деградация, очередь, повтор запроса, а не падение всей системы
- Настроена распределённая трассировка запросов — иначе отладка проблемы «на стыке» сервисов займёт часы вместо минут
- Выгода от разделения (масштабирование, независимый релиз, изоляция отказа) выше, чем стоимость сетевого взаимодействия и оркестрации
Если хотя бы два-три пункта не выполняются, разумнее остаться в модульном монолите ещё на один цикл развития продукта и вернуться к вопросу, когда сигналы станут однозначнее. Подробнее о самой идее постепенного перехода и происхождении термина «monolith first» можно почитать в материале Мартина Фаулера.
Частые вопросы
Можно ли начинать новый проект с микросервисов?
Технически можно, но для нового продукта без устоявшихся границ это обычно означает, что вы распределяете систему раньше, чем поняли, где проходят реальные границы доменов. Большинство успешных микросервисных систем выросли из монолита, когда границы уже были видны на практике, а не придуманы заранее.
Сколько микросервисов — это нормально для старта?
Для первого разделения достаточно одного-двух сервисов, выделенных под самый нагруженный или самый независимый по жизненному циклу домен. Планировать сразу десяток сервисов на старте — почти всегда признак преждевременной декомпозиции, а не зрелой архитектуры.
Что такое модульный монолит простыми словами?
Это одно развёртываемое приложение, внутри которого код разбит на модули с чёткими границами и собственным API между ними, как если бы это были будущие сервисы, только без сети между ними. Переход к отдельным сервисам из такого монолита технически проще, чем из кода без внутренних границ.
Как понять, что команда готова к микросервисам организационно?
Готовность — это не желание, а штат: отдельная команда может взять на себя эксплуатацию, мониторинг и дежурство по своему сервису без постоянной помощи соседей. Если такой команды пока нет, разделение добавит инфраструктурную нагрузку, которую некому нести.
Нужна ли отдельная база данных для каждого микросервиса?
Да, это одно из немногих жёстких правил: сервис, который читает и пишет в общую с другими сервисами базу, на практике остаётся распределённым монолитом, а не микросервисной системой, даже если код физически разнесён по разным процессам.
Что такое паттерн «душитель» (strangler fig)?
Это стратегия постепенной замены части монолита новым сервисом: перед старым кодом ставится прокси, трафик на конкретную функциональность постепенно переключается на новую реализацию, а старый код удаляется только после того, как новый путь полностью доказал свою надёжность.
Можно ли вернуться от микросервисов к монолиту?
Да, и это не редкость: если разделение оказалось преждевременным, сервисы с общей базой данных и синхронными цепочками вызовов можно консолидировать обратно в один деплой, сохранив внутри него уже выделенные модульные границы.



