The post has been translated automatically. Original language: Russian
The decision to switch to microservices is often made under the influence of the experience of large technology companies, rather than based on the actual needs of a particular product. As a result, a small team gets a distributed system with associated costs — network delays between services, complicated testing, and the need to manage infrastructure — in the absence of problems that the microservice architecture is designed to solve. The reverse situation is also common: the team has been maintaining a monolith for years for reasons of familiarity, although the system has already reached a scale where a single code base slows down development and increases the risk with each release. In both cases, the decision is made not on the basis of analysis, but by inertia or by analogy with other people's experience.
Fork in the road: which question determines the choice

It is advisable to build the choice of architecture as a sequence of specific issues, rather than as a one-time solution "for" or "against" a fashionable approach.
The first issue is the size of the team and the organizational structure. If a single team of up to 8-10 people is working on a product, capable of keeping the entire code base in mind, the advantages of independent service deployment, as a rule, do not outweigh the costs of maintaining a distributed system. Microservice architecture has a tangible effect when several independent teams have to develop and release their parts of the system without blocking each other.
If there is more than one team, the next question is how well the boundaries of the subject area are defined. Microservices involve decomposition along stable domain boundaries; if the boundaries between product modules continue to actively change, premature separation into services will lead to a constant revision of the interfaces between them — which is more expensive than similar refactoring inside the monolith.
If the teams are separated and the domain boundaries are stable, the final criterion is the scaling requirements of individual parts of the system. When different components of a product require significantly different computing loads — for example, a video processing module and a user profile module—separate scaling becomes a significant practical advantage rather than a theoretical consideration.
Recommendations on product stages
At an early stage, when the product is still looking for market fit and functionality is changing on a weekly basis, monolith is almost always preferable: the speed of making changes is more important than the possibility of independent deployment, and the boundaries of the modules have not yet been formed enough to fix them as separate services.
At the growth stage, when the product has found steady demand and the team is expanding to several independent groups, it is advisable to separate not the entire system into separate services, but separate modules with the most stable boundaries and the highest load — leaving the bulk of the functionality in a monolith until there is a specific reason for further separation.
At the maturity stage, with a well—established domain model and a staff of several dozen engineers, distributed architecture is usually already organizationally justified - it allows teams to work and release changes independently of each other, which at this scale becomes a more significant factor than the complexity of operating a distributed system.
It makes sense to review an architectural decision regularly, rather than making it once at the start.: what was the right choice for a team of five people naturally ceases to be optimal for a team of fifty — and vice versa, premature complication of architecture creates costs that are not beneficial at an early stage.
Решение о переходе на микросервисы нередко принимается под влиянием опыта крупных технологических компаний, а не исходя из фактических потребностей конкретного продукта. В результате небольшая команда получает распределенную систему с сопутствующими издержками — сетевые задержки между сервисами, усложненное тестирование, необходимость управлять инфраструктурой — при отсутствии проблем, которые микросервисная архитектура призвана решать. Обратная ситуация также распространена: команда годами сохраняет монолит из соображений привычности, хотя система уже достигла масштаба, при котором единая кодовая база тормозит разработку и повышает риск при каждом релизе. В обоих случаях решение принимается не на основе анализа, а по инерции или по аналогии с чужим опытом.
Развилка: от какого вопроса зависит выбор

Выбор архитектуры целесообразно строить как последовательность конкретных вопросов, а не как разовое решение «за» или «против» модного подхода.
Первый вопрос — размер команды и организационная структура. Если над продуктом работает одна команда до 8–10 человек, способная удерживать в голове всю кодовую базу, преимущества независимого развертывания сервисов, как правило, не перекрывают издержки на поддержку распределенной системы. Микросервисная архитектура дает ощутимый эффект тогда, когда несколько независимых команд должны разрабатывать и выпускать свои части системы, не блокируя друг друга.
Если команда не одна, следующий вопрос — насколько четко определены границы предметной области. Микросервисы предполагают декомпозицию по устойчивым доменным границам; если границы между модулями продукта продолжают активно меняться, преждевременное разделение на сервисы приведет к постоянному пересмотру интерфейсов между ними — что дороже, чем аналогичный рефакторинг внутри монолита.
Если команды разделены, а границы предметной области стабильны, финальный критерий — требования к масштабированию отдельных частей системы. Когда разные компоненты продукта нуждаются в существенно разной вычислительной нагрузке — например, модуль обработки видео и модуль профиля пользователя, — раздельное масштабирование становится значимым практическим преимуществом, а не теоретическим соображением.
Рекомендации по стадиям продукта
На ранней стадии, когда продукт еще ищет соответствие рынку и функциональность меняется еженедельно, монолит почти всегда предпочтительнее: скорость внесения изменений важнее возможности независимого развертывания, а границы модулей еще не сформировались настолько, чтобы их фиксировать в виде отдельных сервисов.
На стадии роста, когда продукт нашел устойчивый спрос и команда расширяется до нескольких независимых групп, целесообразно выделять в отдельные сервисы не всю систему целиком, а отдельные модули с наиболее стабильными границами и наибольшей нагрузкой — оставляя основную часть функциональности в монолите до тех пор, пока не появится конкретная причина для дальнейшего разделения.
На стадии зрелости, при устоявшейся доменной модели и штате из нескольких десятков инженеров, распределённая архитектура обычно уже оправдана организационно — она позволяет командам работать и выпускать изменения независимо друг от друга, что на этом масштабе становится более значимым фактором, чем сложность эксплуатации распределённой системы.
Архитектурное решение имеет смысл пересматривать регулярно, а не принимать один раз на старте: то, что было верным выбором для команды из пяти человек, закономерно перестает быть оптимальным при команде из пятидесяти — и наоборот, преждевременное усложнение архитектуры создает издержки, не приносящие пользы на ранней стадии.