Почему микросервисы — плохой выбор для старта? Или как не утопить проект в техническом долгу.
Микросервисы стали настоящим символом современной разработки. Все хотят иметь гибкую, масштабируемую архитектуру, состоящую из маленьких независимых изолированных сервисов. Идея выглядит простой и привлекательной: небольшие независимые команды работают над отдельными сервисами, быстро выпускают обновления, легко поддерживают и развивают систему.
Но часто при выборе микросервисной архитектуры на старте проекта, особенно на этапе MVP, эта мечта превращается в кошмар. И тогда происходит деградация архитектуры системы в несколько этапов.
Старт: «Мы не знаем, что строим, но уже делим на сервисы»
На старте домен еще не определен. Мы пытаемся угадать, какие части системы будут автономными, но это похоже на путешествие в темноте.
Что происходит:
- Неправильные границы сервисов - часто границы проводятся технически (по типу сущностей: "вот сервис Пользователей", "вот сервис Заказов"), а не по бизнес-возможностям.
- Скрытые зависимости - даже если сервисы формально разделены, изменения в бизнес-логике часто требуют правок в нескольких местах. Вместо гибкости мы получаем необходимость координировать изменения между командами, тестировать интеграции и бояться релизов.
- Сложная инфраструктура с нуля - микросервисы требуют CI/CD для каждого сервиса, мониторинг, логирование, управление конфигурациями, контейнеризацию и оркестрацию (Kubernetes, Docker). Но наш MVP ещё даже не окупился, а команда уже тратит время на настройку кластеров вместо того, чтобы тестировать гипотезы.
Рост: «Мы знаем больше, но уже поздно что-то менять»
Когда проект переходит в фазу пост MVP мы начинаем понимать, как должен выглядеть продукт. Но микросервисы, созданные в спешке, начинают нас тормозить.
Что происходит:
- Несостоявшиеся автономность и масштабируемость - мы планировали, что некоторые сервисы будут работать независимо, но теперь они обмениваются данными через API каждые 5 минут. Масштабирование одного сервиса требует масштабирования другого, потому что нагрузка на них связана. Вместо экономии на ресурсах вы получаете рост затрат без реальной пользы.
- Технический долг, который висит мертвым грузом - каждое изменение в домене (например, новые правила валидации) требует переписывать API между сервисами. Мы добавляем адаптеры, мапперы, шлюзы — и в итоге получаем сложную систему, которую трудно поддерживать. Новые разработчики месяцами разбираются в зависимостях, а старые боятся трогать «рабочее» решение.
- Кошмар с транзакциями и согласованностью - в монолите мы могли использовать ACID-транзакции для обеспечения целостности данных. В микросервисах приходится мириться с eventual consistency или писать сложные механизмы SAGA. Ошибка в одном шаге может оставить систему в несогласованном состоянии, а восстановление — это боль.
Зрелость: «Мы хотим переделать всё, но боимся»
Когда проект достигает зрелости, становится очевидно, что архитектура не соответствует реальным потребностям. Но переезд на новую структуру — это риск, время и деньги.
Что происходит:
- Рефакторинг превращается в переписывание - чтобы исправить границы сервисов, необходимо переписать API, перенести данные, изменить интеграции. Это может занять месяцы, а мы не хотим останавливать развитие продукта.
- Команды начинают "пробуксовывать" - микросервисы изолируют не только код, но и команды. Вместо быстрых решений мы получаем долгие обсуждения, формальные контракты API и конфликты интересов.
- Масштабирование становится обузой - мы платим за инфраструктуру, которая изначально не была нужна. Вместо 100 строк кода в монолите мы тратим ресурсы на 10 сервисов, каждый из которых требует своего мониторинга и резервного копирования.
❓Что же тогда выбрать?
Если не микросервисы, то что? Обратно к громоздким монолитам? Ответ прост: стоит начать с чего-то более простого, но при этом дающего возможность для дальнейшего роста.
💡Выход есть: начните с модульного монолита
Микросервисы — это не про «масштабируемость ради масштабируемости», а про осознанное разделение на автономные части. Но чтобы к этому прийти, нужно сначала понять домен.
Модульный монолит — это компромисс, который даёт:
- Гибкость на старте — вы делите код на модули с чёткими интерфейсами, но без сетевых проблем.
- Контроль над зависимостями — проблемы в домене решаются внутри одной базы кода, без API-контрактов.
- Путь к микросервисам — когда домен станет ясен, модули можно выделить в отдельные сервисы — по факту, а не вслепую.
Микросервисы — не точка входа, а точка выхода. Правильная архитектура — эволюционная. Многие популярные и авторитетные авторы — Мартин Фаулер, Роберт Мартин, Сэм Ньюман, Крис Ричардсон (и я очень поддерживаю их точку зрения) предлагают начинать разработку с монолитов.
Статья Фаулера (Martin Fowler) о "Monolith First" подходе
В следующем посте разберем подробно, что такое модульный монолит, как его правильно строить и какие подводные камни ждут на этом пути.
Мой телеграм-канал по ссылке: telegram