Осторожность с микросервисами оправдана из-за расходов, которые команды стабильно недооценивают на старте.
В монолите всё просто: вызовы функций внутри одного процесса. Микросервисы заменяют это сетью. Теперь каждый запрос идёт через разные машины, балансировщики, service mesh и слои аутентификации — больше точек отказа и больше инфраструктуры. Внезапно нужны service discovery (как сервисы находят друг друга), распределённая трассировка, централизованные логи и мониторинг, который понимает топологию сервисов. Каждый кусок по отдельности необходим — а вместе они сложны и недёшевы. Дублирование данных съедает хранилище, болтовня между сервисами раздувает счёт за исходящий трафик. У Prime Video, напомню, перегонка данных через S3 стоила дороже самой обработки.
В микросервисах сложность не в том, чтобы написать код, а в том, чтобы заставить распределённые части разговаривать. Распределённое состояние вынуждает писать оборонительный код, который вечно проверяет частичные сбои. В монолите разработчик проходит весь путь выполнения от начала до конца в одном репозитории. В микросервисах одна фича может расползтись по четырём-пяти репозиториям с разными зависимостями и релизными циклами. Добавление одного поля запускает недели согласований: обнови сервис, дождись, пока потребители его примут, проверсионируй API, оркеструй раскатку. То, что компилятор поймал бы в монолите на этапе сборки, теперь всплывает как ошибка в проде.
Интеграционные и сквозные тесты в монолите быстрые, потому что гоняются локально, в памяти. Распределённая система такой роскоши не даёт: для настоящей уверенности тесты должны пересекать множество сервисных границ — а значит, они медленнее, капризнее и требуют staging-окружения, похожего на прод. Это фактически удваивает инфраструктуру и растягивает обратную связь. Многие узнают об этом лишь тогда, когда сам набор тестов становится бутылочным горлышком. Добавьте сюда оркестрацию релизов, несовместимость версий («сервис A дружит с B 2.1, но ломается на 2.2») и частично применённые деплои, которые потом мучительно откатывать.
Самое недооценённое — консистентность данных между сервисами. Монолит живёт на ACID-транзакциях: операция либо проходит целиком, либо целиком откатывается. Микросервисы режут это по живому, и вам приходится строить распределённые саги (многошаговые процессы с логикой компенсации), мириться с eventual consistency (данные становятся верными лишь спустя время) или писать компенсирующий код для отмены частичных сбоев. То, что было одной транзакцией БД, теперь растягивается на сетевые прыжки, ретраи и полусбои. Отлаживать рассогласованный заказ или платёж, когда состояние размазано по сервисам, — отдельный жанр страданий.
И всё это не складывается, а перемножается. Операционная сложность усложняет отладку, замедляет тесты, повышает риск релизов и множит инциденты. Микросервисы не переносят сложность из кода в эксплуатацию — они добавляют налог на каждый этап инженерного процесса. Если ваш масштаб его не требует, налог почти всегда съедает выгоду.
Если каждый сетевой прыжок добавляет сложности и денег к счёту — оправдывает ли ваш сценарий эту цену?
Прежде чем резать систему на сервисы, стоит честно спросить себя: а не дадут ли более простые и аккуратные архитектуры сопоставимую масштабируемость — без налога на распределённую сложность? Два достойных кандидата — модульный монолит и сервис-ориентированная архитектура.
В отличие от классического монолита, который со временем превращается в спутанный клубок, модульный монолит держит жёсткие внутренние границы за счёт явных API модулей и дисциплины разделения. Каждый модуль выставляет чёткий интерфейс, команды работают независимо — но деплоится всё как единая система. Кент Бек в своём разборе «Монолит → Сервисы» формулирует суть: модульный монолит управляет связностью организационной дисциплиной, а не сетью. Модули общаются через явные контракты, как микросервисы, но используют быстрые и надёжные вызовы функций вместо HTTP, уязвимого к задержкам и полусбоям.
Почему это работает: операции проще (организация уровня микросервисов при простоте монолита); согласованность строже (полноценные ACID-транзакции); отладка человечнее (одна наблюдаемая система, без поиска иголки в стоге логов); производительность выше (вызов функции бьёт сетевой прыжок). И это не теория: кодовая база Shopify на 2,8 млн строк перемалывает 30 ТБ данных в минуту, при этом разные команды владеют разными модулями, а катится всё вместе. Facebook устроен похоже. А благодаря Spring Modulith, инструментам в Django, Laravel и Rails модульные монолиты вполне могут стать мейнстримом ближайших лет.
Сервис-ориентированная архитектура (SOA) занимает место между монолитом и микросервисами: вместо десятков крошечных сервисов — несколько крупных, привязанных к доменам. Вместо того чтобы дробить аутентификацию, профили и уведомления на отдельные микросервисы, SOA соберёт их в единый «сервис пользователя» — координации меньше, автономность и прицельное масштабирование на месте. Это корпоративная модульность без накладных расходов ультрамелкого дробления. И в масштабе SOA себя доказала: Norwegian Air Shuttle строила на ней гибкость своих полётных операций, а Credit Suisse ещё в начале 2000-х обрабатывала через SOA миллионы запросов в день.
Если более простые архитектуры дают сопоставимую масштабируемость — зачем вы сознательно выбираете сложность микросервисов?
Автор: Коробов Алексей
© Коробов А.Е., 2026