
Выживание стартапа зависит от того, насколько быстро вы сможете вносить доработки, поставлять новые функции и обеспечивать ценность для конечных потребителей. И во всём этом важную роль играет выбранная вами базовая архитектура. Кроме того, оперативность команды напрямую зависит от технологического стека и используемого языка программирования. Неудачная архитектура, особенно на базе незрелых микросервисов, может сильно подорвать продуктивность и привести к срыву планов по выпуску продукта.
Я усвоил всё это, когда работал над новаторскими проектами в начинающих стартапах, где в качестве программной архитектуры выбирались сомнительные решения, которые вели к недоделанным сервисам и хрупким, перемудрёным локальным конфигурациям, а также подрывали дух разработчиков, которые не тянули излишнюю сложность.
Ну и прежде чем описывать подводные камни такого решения, уточню, на что конкретно вы подписываетесь, когда слишком рано переходите на микросервисы:
Слабое место | Как проявляется | Последствия для разработчика |
Сложность развёртывания | Необходимость оркестрировать более 5 сервисов для работы одной функции | Лишние часы работы над каждым релизом |
Хрупкость локальной разработки | Расползание Docker, сломанные скрипты, платформо-зависимость | Медленный онбординг, частые сбои |
Дубликация CI/CD | Несколько пайплайнов с повторяющейся логикой | Дополнительная плата за каждый сервис |
Связывание сервисов | «Разделённые» сервисы, тесно связанные общим состоянием | Медленное внесение изменений, дополнительные хлопоты по координации |
Издержки наблюдаемости | Распределённая трассировка, логирование, мониторинг | Требуются недели для должной настройки всех инструментов |
Фрагментация наборов тестов | Тесты разбросаны по сервисам | Ненадёжные тесты, низкая уверенность |
▍ Монолит вам не враг

Если вы создаёте продукт SaaS, даже простая обёртка базы данных SQL в конечном итоге может привнести много внутренней сложности, связанной с её бизнес-логикой. Вы также можете прибегать к различным интеграциям и фоновым задачам, которые позволяют преобразовывать один набор данных в другой.
Со временем ваше приложение может обрасти ненужными функциями и стать беспорядочным. Монолиты же отличаются тем, что продолжают работать — даже в беспорядочном виде они позволяют команде акцентировать внимание на самом важном:
- выживание;
- создание ценности для клиента
Самое большое преимущество монолитов в простоте их развёртывания. Как правило, подобные проекты создаются на базе существующих фреймворков — это может быть Django для Python, ASP.Net для C#, Nest.js для Node.js и так далее. Придерживаясь монолитной архитектуры, вы получаете значительное преимущество перед вычурными микросервисами — обширную поддержку со стороны опенсорсного сообщества и мейнтейнеров проекта, которые изначально создавали эти фреймворки для обеспечения работы в виде единого процесса, монолитного приложения.
Расскажу одну историю. Как-то в стартапе, занимавшемся недвижимостью, я вёл команду фронтенда и периодически консультировал ребят из бэкенда в выборе технологий. Так вот, наше приложение создавалось на Laravel и претерпело интересную эволюцию. Начиналось оно с небольшой информационной таблицы для риелторов, но в итоге разрослось в куда более масштабную систему.
Со временем приложение превратилось в многофункциональный программный пакет, который обрабатывал сотни гигабайт документов и интегрировался с десятками сторонних сервисов. При этом он всё также опирался на откровенно простой стек PHP, функционирующий на сервере Apache.
Наша команда активно налегала на лучшие практики, рекомендованные сообществом Laravel. И это себя оправдало. Мы смогли значительно масштабировать возможности приложения, продолжая соответствовать задачам и ожиданиям бизнеса.
Интересно, что нам ни разу не пришлось разделять систему на микросервисы или применять более сложные паттерны инфраструктуры. Таким образом мы избежали большого объёма непредвиденной сложности. Простота архитектуры дала нам важный рычаг для решения задач. И это отражает опыт других людей. К примеру, в статье компании Basecamp «Majestic Monolith» авторы расписывают, почему на начальных этапах простота подобна суперсиле.
Люди нередко сетуют, что сложно делать монолиты масштабируемыми, но подобные сложности могут быть вызваны неудачной модульной структурой ПО.
Вывод: грамотно структурированный монолит позволяет команде сосредоточиться на поставке продукта, а не тушении «пожаров».
▍ Но разве микросервисы не являются «лучшей практикой»?
Многие инженеры сразу начинают с микросервисов, считая, что «это правильный путь». Да, при больших масштабах они помогают. Но в стартапе аналогичная сложность ведёт к торможению разработки. Микросервисы оправдывают себя, только когда у вас есть реальные узкие места, препятствующие масштабированию, большие команды или независимо развивающиеся направления.
А до этого? До этого вы платите всю ту же цену, но преимуществ не получаете. То есть та же дублирующаяся инфраструктура, хрупкие локальные конфиги и медленное внесение доработок. Например, компания Segment именно по этой причине в конечном итоге отыграла назад разделение на микросервисы — слишком много затрат при недостаточной ценности.
Вывод: микросервисы — это инструмент для масштабирования, а не стартовый шаблон.
▍ Когда микросервисы не к месту (особенно на ранних этапах)
В одной из начинающих команд, которую я консультировал, решение разделить сервисы создало больше хлопот по координации разных отделов, нежели принесло технической пользы.
Архитектура определяла не только форму кода, но также схему планирования, оценки и поставки продукта. Причём эти организационные издержки на первых порах легко упустить из виду, а потом становится слишком поздно.

Вот несколько наиболее распространённых анти-паттернов, которые могут просочиться в систему на ранних этапах.
▍ 1. Произвольные границы сервисов

В теории мы часто видим предложения разделять ПО на основе бизнес-логики — пользовательский сервис, сервис продукции, сервис заказов и так далее. Такой подход часто заимствуется из принципов предметно-ориентированного дизайна (Domain-Driven Design, DDD) или чистой архитектуры (Clean Architecture), которые имеют смысл в больших масштабах. В случае же начинающих продуктов, ещё не достигших стабильности и надёжности, они могут привести к преждевременному окостенению структуры.
В итоге вы получаете:
- общие базы данных;
- вызовы между сервисами в простых рабочих потоках;
- связывание под видом «разделения».
Ещё в одном проекте я наблюдал, как команда разделила пользователя, аутентификацию и авторизацию в отдельные сервисы. Это усложнило развёртывание и затруднило координацию сервисов при любой операции API, какую бы разработчики ни создавали.
В реальности бизнес-логика не отображается непосредственно в границы сервиса. Преждевременное разделение может сделать систему более хрупкой и часто замедляет внесение изменений.
Вместо этого нужно точечно изолировать узкие места, опираясь на реальный план масштабирования, а не теоретическую элегантность.
Когда я обучал начинающие команды, мы иногда использовали для симуляции будущего разделения сервисов внутренние переключатели деплоев — не создавая операционных издержек. Это позволяло продакт-менеджерам и инженерам плавно исследовать границы возможностей, прежде чем фиксировать недостаточно зрелую инфраструктуру.
Вывод: разделяйте систему не по теории, а по фактическим узким местам.
▍ 2. Расползание репозитория и инфраструктуры
При разработке приложения обычно важно следующее:
- согласованность стиля кода (линтинг);
- инфраструктура тестирования, включая проверку интеграции;
- конфигурация локальной среды;
- документация;
- конфигурация CI/CD.
При работе с микросервисами всё это нужно умножать на количество сервисов. Если ваш проект имеет структуру монолита, вы можете упростить себе жизнь, наладив централизованную конфигурацию CI/CD (при работе с GitHub Actions или GitLab CI). Некоторые команды разделяют микросервисы по разным репозиториям, что сильно усложняет сохранение согласованности кода и одинаковых конфигураций без привлечения дополнительных инструментов, а значит и усилий.

Для команды из трёх человек это перебор. Переключение между репозиториями и дополнительные инструменты увеличивают время разработки каждой функции.
▍ Устранение проблем за счёт использования единого репозитория и языка программирования
Исправить эту проблему можно по-разному. В молодых проектах самое важное — это хранить весь код в едином репозитории. Такой подход гарантирует присутствие в продакшене одной версии программы, а также упростит координацию код-ревью и взаимодействие внутри небольших команд.
В случае проектов Node.js я настоятельно рекомендую использовать инструмент
nx
или turborepo
, так как они:- упрощают настройку CI/CD в подпроектах;
- поддерживают кэширование сборки на основе графа зависимостей;
- Позволяют рассматривать внутренние сервисы как библиотеки TypeScript (с помощью импортов ES6).
Эти инструменты экономят время, которое в противном случае тратится на связующий код или очередное продумывание оркестрации. Но есть у них и существенные недостатки:
- сложные деревья зависимостей могут быстро разрастаться;
- настройка производительности CI имеет свои особенности;
- иногда для сокращения времени сборки требуется более быстрый инструментарий (например, bun).
Итак: инструменты вроде
nx
или turborepo
в небольших командах повышают скорость работы с единым репозиторием — если только вы готовы вкладываться в поддержку их чистоты.При разработке микросервисов на базе Go на ранних стадиях будет удобно трудиться в едином пространстве, используя директиву
replace
в go.mod
. В конечном итоге по мере расширения ПО можно будет без лишних усилий выделить модули Go в отдельные репозитории. Вывод: единый репозиторий с общей инфраструктурой экономит ваше время, а также обеспечивает согласованность и душевный покой.
▍ 3. Проблемы в локальной среде ведут к утрате скорости
Если для локального запуска вашего приложения требуется три часа, кастомный скрипт оболочки и марафон из контейнеров Docker, значит вы утратили скорость.
Молодые проекты часто страдают от:
- недостатка документации;
- устаревших зависимостей;
- применения техник, опирающихся на конкретную ОС (например, конфигурации под Linux).
Из своего опыта могу сказать, что проекты, которые мне доставались от других команд, часто создавались под одну операционную систему. Некоторые разработчики предпочитали писать под macOS и никогда не озадачивались поддержкой своих скриптов оболочки под Windows. В командах, с которыми я сотрудничал, бывали инженеры, работавшие на машинах с Windows. И им часто приходилось переписывать скрипты оболочки или капитально перестраивать процесс налаживания работы локальной среды.
Со временем мы стандартизировали настройку среды для ОС разработчиков, чтобы уменьшить трения внутри команды. Это стало небольшим вложением, которое позволило сэкономить немало часов работы с приходом каждого нового инженера. Было нелегко, но мы осознали всю важность того, чтобы код запускался на ноутбуке любого нового разработчика, какую бы систему тот ни использовал.
Приведу пример ещё одного проекта, где инженер создал хрупкую конфигурацию микросервиса, который поток обработки контейнеров Docker смонтировал в локальную файловую систему. Естественно, когда ваш ПК работает под Linux, вы платите очень мало за выполнение процессов в виде контейнеров.
Но вот приход в команду нового фронтенд-разработчика, у которого на рабочем ноутбуке стояла Windows, привёл к кошмару. Ему приходилось запускать аж десять контейнеров, чтобы просто увидеть свой UI. При этом всё постоянно ломалось — то тома, то сеть, то проблемы с совместимостью контейнеров — и сама конфигурация была очень плохо задокументирована. Всё это создало немало трений в процессе онбординга.
В итоге мы вместе придумали прокси на Node.js, который имитировал конфигурацию nginx/Docker без контейнеров. Да, элегантности этому решению не хватало, зато оно позволило новому разработчику, наконец, включиться в общую работу.

Вывод: если ваше приложение работает только в одной ОС, то от провала продуктивности вас отделяет лишь один ноутбук.
Совет: в идеале старайтесь делать git clone <repo> && make up
, чтобы проект запускался локально. Если это невозможно, необходимо вести актуальный файл README с инструкциями для Windows/macOS/Linux. Сегодня существуют языки программирования и наборы инструментов, которые плохо работают под Windows (например, OCaml), но популярный программный стек прекрасно себя чувствует в любой из распространённых операционных систем. Ограничение конфигурации лишь одной ОС зачастую говорит о недостаточном продумывании процесса разработки.
▍ 4. Несоответствие технологий
Помимо архитектуры, стек технологий также определяет степень болезненности микросервисов — не каждый язык хорошо дружит с этой архитектурой.
- Node.js и Python: такая комбинация отлично подходит для быстрого внесения доработок, но усложняет управление сборкой артефактов, версиями зависимостей, а также обеспечение согласованности среды выполнения.
- Go: компилируется в статические бинарные файлы, обеспечивает быструю сборку и низкие операционные издержки. Более гармонично подходит в случаях, когда требуется разделение.
Очень важно выбрать подходящий технологический стек с самого начала. Если вы ориентированы на быстродействие, обратите внимание на JVM с её экосистемой и возможностью масштабного развёртывания и выполнения артефактов в архитектурах на базе микросервисов. Если же вас интересует частое внесение доработок и оперативное прототипирование без масштабирования инфраструктуры развёртывания, то вполне подойдёт что-то вроде Python.
Довольно часто команды осознают, что выбрали совсем неподходящую технологию, которая изначально такой не казалась. В итоге им приходится вкладываться в переписывание бэкенда на другом языке (как в этом случае, когда инженерам пришлось выкручиваться из ситуации со старой кодовой базой на Python 2 и в итоге переносить её на Go).
С другой же стороны, если вам действительно это важно, можете соединить несколько языков программирования с помощью таких протоколов, как gRPC или асинхронного обмена сообщениями. И часто делают именно так.
Иногда вы подходите к точке, когда нужно расширить функциональность с привлечением машинного обучения или ETL-инструментов. В таком случае вы просто отдельно создаёте МО-инфраструктуру на Python, поскольку он имеет богатую экосистему предметно-ориентированных библиотек, которой не может похвастаться ни один другой язык. Но такие решения нужно принимать, когда в штате есть достаточно специалистов. В противном случае небольшая команда погрузится в пучину сложности совмещения нескольких программных стеков.
Вывод: сопоставляйте используемые технологии со своими возможностями, а не амбициями.
▍ 5. Скрытая сложность: коммуникация и мониторинг
Микросервисы несут с собой незримый набор потребностей:
- обнаружение сервиса;
- версионирование API;
- повторы, защитные механизмы вроде circuit breaker и fallback;
- распределённая трассировка;
- централизованное логирование и предупреждение.
В монолите баг может раскрываться простой трассировкой стека. В распределённой же системе это подразумевает вопрос «Почему сервис А падает, когда развёртывание сервиса В отстаёт от развёртывания С на 30 секунд?» Здесь вам придётся прилично вложиться в набор технологий для наблюдаемости. Чтобы сделать всё «правильно», потребуется определённым образом снарядить ваше приложение. Это может подразумевать интеграцию OpenTelemetry для поддержки трассировки или привлечение инструментов облачного провайдера вроде AWS XRay, если вы реализуете крупную бессерверную систему. Но в этот момент вам придётся полностью сместить акцент с кода приложения на создание сложной инфраструктуры мониторинга, которая обеспечит уверенность в должном функционировании системы в продакшене.
Естественно, какие-то механизмы наблюдаемости нужно реализовывать и в монолитах, но в них всё это намного проще, нежели согласование подобных действий во множестве сервисов.
Совет: уясните, что распределённые системы требуют вложений, поэтому их использование влечёт за собой целый класс новых инженерных задач.
▍ Когда микросервисы оправданы
Несмотря на упомянутые сложности, в некоторых случаях разделение на уровне сервисов оказывается очень кстати. Это может быть:
- Изоляция рабочей нагрузки: стандартным примером будет следование лучшим практикам AWS по использованию уведомлений S3 — когда изображение загружается в S3, активируется процесс изменения его размера/оптического распознавания символов и тому подобное. Польза в том, что это позволяет выделить непонятные библиотеки обработки данных в собственный изолированный сервис и закрепить за его API только обработку изображений и генерацию вывода на основе загруженных данных. В итоге вышестоящие клиенты, загружающие данные в S3, не будут связаны с этим сервисом, плюс уменьшатся издержки, связанные с его оснащением, так как он будет относительно прост.
- Расходящиеся потребности в масштабировании: представьте, что создаёте ИИ-продукт. Одна из его частей (веб API), которая активирует рабочие нагрузки для модели МО и выдаёт результаты, не требует много ресурсов, так как взаимодействует в основном с базой данных. Но вот модель МО выполняется на GPU, является тяжеловесной и требует использования особых машин с поддержкой GPU и дополнительных настроек. Разделив эти части приложения в отдельные сервисы, работающие на разных машинах, вы сможете масштабировать их независимо.
- Различные требования к среде выполнения: предположим, у вас есть легаси-код, написанный на C++. В таком случае перед вами 2 варианта — магически перевести его на язык основной программы или найти способы интегрировать его в неё. В зависимости от сложности легаси-приложения, вам может потребоваться писать связующий код, а также реализовывать дополнительные сетевые механизмы и протоколы для взаимодействия с этим сервисом. Но суть в том, что из-за несовместимости сред выполнения вам наверняка придётся выделить это приложение в отдельный сервис. Более того, вы также можете написать основное приложение на C++, но из-за различий в конфигурациях компилятора и зависимостях вам не удастся легко скомпилировать всё это вместе в едином исполняемом файле.
Крупные компании сталкивались с аналогичными проблемами. К примеру, команда разработки в Uber описала свой переход к предметно-ориентированной архитектуре микросервисов — и не из-за её теоретической чистоты, а в результате возникновения реальной сложности взаимодействия между командами и достижения пределов масштабирования. Их статья является хорошим примером того, как микросервисы могут работать, когда у вас достаточно зрелая организация, и есть достаточный операционный ресурс для их поддержки.
В одном проекте, который тоже касался работы с недвижимостью, нам от предыдущей команды достался код Python, который выполнял аналитику, загружая полученные данные в БД MS-SQL. В той ситуации мы поняли, что будет излишне затратно и бессмысленно создавать поверх такого механизма приложение на Django. В имевшемся коде использовались другие зависимости среды выполнения, и он был достаточно изолирован, поэтому мы держали его отдельно и возвращались к нему, только когда что-то шло не так. Такой подход сработал даже для нашей небольшой команды, поскольку этот сервис аналитики редко требовал изменений или обслуживания.
Вывод: используйте микросервисы при наличии расходящихся в своей сути рабочих процессов, а не просто, потому что они сулят чистоту.
▍ Практические советы для стартапов
Если вы готовите свой первый продукт, вот вам несколько рекомендаций:
- Начинайте с монолита. Выберите распространённый фреймворк и сосредоточьтесь на реализации функциональности. Любого известного фреймворка с лихвой хватит для создания API или сайта и обслуживания пользователей. Не гонитесь за хайпом. Пусть это будет рутинный путь, зато впоследствии вы сами себе скажете «спасибо».
- Один репозиторий. Не озадачивайтесь разделением кода на несколько репозиториев. Я работал с основателями компаний, которые хотели разделить репозиторий для уменьшения риска кражи подрядчиками их интеллектуальной собственности — обоснованное беспокойство. Но на практике это обеспечивало больше напряжения, нежели безопасности — замедление сборок, фрагментирование цикла CI/CD и слабая видимость процессов среди команд. В итоге такая неэффективная защита интеллектуальной собственности просто не стоила связанных с ней операционных хлопот, особенно притом, что внутри единого репозитория управляться с нужными механизмами доступа было проще. В начинающих проектах ясность и скорость важнее теоретического прироста безопасности.
-
Простейшая локальная конфигурация. Используйте
make up
. Если этого недостаточно, тщательно продумывайте все шаги, записывайте видео с экрана и добавляйте скриншоты. Если ваш код будет выполнять начинающий разработчик, он наверняка столкнётся с проблемой, и вам придётся объяснять, как её решить. Я на личном опыте понял, что документирование всех возможных проблем в каждой операционной системе избавляет от необходимости тратить время на объяснение, почему определённые моменты в локальном сеттинге не работают. -
На начальных этапах вкладывайтесь в CI/CD. Даже если это простой HTML-код, который несложно скопировать (
scp
) на сервер вручную, этот процесс можно автоматизировать с помощью систем контроля версий и CI/CD. Когда конфигурация должным образом автоматизирована, вы просто забываете об инфраструктуре непрерывной интеграции и сосредотачиваетесь на функциональности. Я видел немало команд и основателей компаний, которые при работе со сторонними подрядчиками зачастую экономят на CI/CD, что приводит к негодованию разработчиков, которым надоедает деплоить всё вручную. - Разделяйте точечно. Разделяйте программу, только когда это точно решит острую проблему. В противном случае лучше вкладываться в модульность и тесты внутри монолита — это можно реализовать быстрее и легче.
Ну и самое главное: оптимизируйте систему под скорость разработки.
Скорость подобна кислороду для вашего стартапа. Преждевременное внедрение архитектуры микросервисов приводит к постепенной утечке этого кислорода, пока в конечном итоге стартап просто не задохнётся.
Вывод: начинайте с простого, придерживайтесь прагматичности и используйте разделение только при необходимости.
▍ Если вы склонитесь к микросервисам
Я сталкивался с проектами, которые переходили на микросервисы раньше, чем следовало бы, и вот несколько рекомендаций на подобный случай:
- Оценивайте свой технологический стек, на который опирается архитектура микросервисов. Вкладывайтесь в развитие инструментов для разработчика. Когда вы разделяете проект на сервисы, вам приходится автоматизировать не только их стек, но также конфигурацию локальной и продакшен среды. В определённых проектах мне приходилось создавать отдельный CLI, который выполнял административные задачи в едином репозитории. В одном случае у нас было 15-20 микросервисов, и для локального деплоя мне пришлось создавать инструмент командной строки, чтобы тот динамически генерировал файлы
docker-compose.yml
, которые бы позволили обычному разработчику легко запускать программу одной командой. - Используйте надёжные протоколы коммуникации между сервисами. Если это асинхронный обмен сообщениями, проследите, чтобы их схемы были согласованы и стандартизованы. Если это REST, обратитесь к документации OpenAPI. В клиентах, отвечающих за межсервисную коммуникацию, нужно реализовать много нештатных операций: повторы с экспоненциальным увеличением периода ожидания, таймауты. Типичный голый клиент gRPC требует ручного налаживания всех этих дополнительных механизмов для исключения спорадических ошибок.
- Проследите, чтобы ваша конфигурация модульных, интеграционных и сквозных тестов была стабильна и при дополнительных разделениях кодовой базы на отдельные сервисы хорошо масштабировалась.
- В небольших проектах, где используется разделение на уровне микросервисов, для согласованной организации кода взаимодействия и механизмов наблюдения лучше задействовать общую библиотеку с типичными вспомогательными функциями. При этом важно сохранять минимальный размер этой библиотеки. Любое серьёзное изменение приведёт к повторной компиляции всех зависимых сервисов — даже если оно их не касается.
- Налаживайте механизмы наблюдения на ранних этапах. Добавляйте структурированные логи JSON и создавайте соответствующие ID для отладки приложения после его развёртывания. Даже простейшие вспомогательные функции, выдающие богатую информацию для журналов (при условии снаряжения приложения правильными инструментами логирования/трассировки) часто экономят время, выявляя подозрительные пользовательские потоки.
Подытожим. Если вы всё равно собираетесь переходить на микросервисы, то должны заранее учитывать сопутствующие издержки в плане дополнительных усилий по развёртыванию и обслуживанию, необходимые для создания конфигурации, с которой сможет работать любой инженер в вашей команде.
Вывод: если вы решили перейти на сложную архитектуру, приложите усилия, чтобы сделать её управляемой.
▍ Заключение
Преждевременный переход на микросервисы приведёт к непосильным издержкам. Придерживайтесь простоты — она позволит вам оставаться на плаву — и прибегайте к разделению, только когда это уже явно необходимо.
Первым делом — выживание. Масштабирование потом. Используйте простейшую систему, которая работает, и оправдывайте каждый привносимый в неё уровень сложности.
Telegram-канал со скидками, розыгрышами призов и новостями IT ?

Комментарии (22)
stan1901
18.05.2025 10:00Мой опыт разработки в "кровавом энтерпрайзе" показывает, что чуть ли не единственное реальное удобство использования микросервисов не технологическое, а организационное - с ними проще "отвязывать" релизные циклы команд друг от друга. Остальные декларируемые удобства за свои 25 лет разработки не встречал почти никогда:
1) Разный техстэк? Возможно, но крупной организации логично его унифицировать во избежание бардака.
2) Независимое масштабирование и изоляция нагрузки? Хороший аргумент, но на практике стараются закладывать ресурсы с запасом и ставить ограничители частоты запросов на всё что можно ради выполнения SLA, подписанного кровью перед бизнесом.
Если очень надо разделять части функциональности, можно сделать несколько "систем", а не "микросервисов". Технически разница небольшая, хотя могут быть нюансы с точки зрения производственного процесса компании (например, системы могут требовать специального учёта и согласования, а микросервисы нет). Но опять же, это не про технологию, а про управление процессом разработки.
Dhwtj
18.05.2025 10:00Разный стек это когда монолит легаси на PHP и нового туда не пишут, только старое. А микросервисы на Go.
Лично я видел распределенную архитектуру только в географически распределенных системах, да и там это была архитектурная ошибка.
организационное - с ними проще "отвязывать" релизные циклы команд друг от друга
В разных языках по разному. C# например позволяет быструю инкрементальную сборку, быструю проверку стат анализаторами только изменившегося модуля (DLL) и даже внутренние долгоживущие сервисы. И нафиг ещё микросервисы надо. А PHP никаких гарантий изоляции не даёт, фреймворки и настройки вмешиваются во всю программу
apcs660
18.05.2025 10:00Однажды столкнулись с проблемой узкого канала у заказчика при использовании распределенной системы при переносе данных из одного репозитория документов в другой.
Консультанты не выяснили что канал между серверами старого и нового репозитория узкий, около мегабайта в секунду, использовался для небольшого трафика. А тут мы по нему погнали сотни млн документов.
Повезло что приложение можно было резать на части (kafka streaming api) с заглушками в файловой системе ( дерево папок с метаданными и контентом).
Второе хорошо что небольшое расстояние, километров 20 - возили хард как Амазон дата трак с дисками....
SirHole
18.05.2025 10:00И ни слова про ИИ. Лично для моих проектов выбор в пользу микросервисов был обусловлен контекстным окном нейронки. Как ни странно нейронки вполне себе успешно переваривают весь микросервис и умудряются писать самостоятельно простой функционал.
Плюс очень просто стало искать исполнителей на фрилансе. Не нужно вводить исполнителя в курс дела проекта. Даётся тз на несколько простых функций без необходимости вводить исполнителя в контекст проекта.
XelaVopelk
18.05.2025 10:00"Самое большое преимущество монолитов в простоте их развёртывания." удивительно как эта байка о простоте развёртывания монолита гуляет так долго. Наверное это для приложений: фронт->бэк->база без связей с другими системами. Если ваш монолит это база на несколько терабайт обвешанная сервисами разной степени мутности как новогодняя ёлка с кучей интеграций, то развёртывание этого монолита станёт весёлым и затейливым квестом.
apcs660
18.05.2025 10:00Был у меня в соседней группе монолит - всем монолитам монолит... Конфиг XML на сотни строк, с кросс ссылками, коннекторами в репозитории, вьюверы и тд. Само приложение тоже неудобное - часть модулей мавен отключено в дефолтном профайле, по коду ничего не найти если не знаешь где. "Метастаза" было бы хорошим названием этому приложению.
Я упирался руками и ногами чтоб не делать что либо в этом проекте - проблема не в коде сделать фикс а проверить билд...
Frankenstine
18.05.2025 10:00Ни слова о k8s, только докер упомянут. А между прочим, микросервисы без k8s теряют смысл.
И ещё плюс микросервисов, не упомянутый никак: в случае ошибки в коде монолита, можно получить нерабочий весь монолит (например, логинится юзер и видит белый лист из-за 500 ошибки в коде функции которая данные из таблички выгребает), в то время как в микросервисной архитектуре ляжет лишь конкретный микросервис (и условно вместо белого листа у юзера будет почти весь интерфейс и белый прямоугольник там где функция должна была вернуть данные для отрисовки графика)
Наконец, пример из жизни: ребята не могут вылить в деплоймент код api сервера, потому что в имеющейся админке монолита который api реализует есть уязвимые сторонние библиотеки, хотя они не используются в работе api и нужен секс по обновлению зависимостей для успокоения анализатора уязвимостей. В случае архитектуры микросервисов, api был бы независим от админки, что упростило бы выкладку.
vmarunin
18.05.2025 10:00Полстатьи про то, что важна скорость разработки на машине конкретного разраба. А в этом случае docker-compose рулит, а k8s вот совсем не рулит
Нет, я работал в разных местах, в том числе и там где рабочий энв был уже в облаке (разными способами) и всё делалось на сервере
Но проще composeFrankenstine
18.05.2025 10:00Если проект - одиночный небольшой сервис вокруг базы данных, то да, а если это проект в котором десяток различных составляющих, неочевидным для данного программиста образом взаимодействующих, он кукухой тронется, пытаясь поднять локально функционирующую копию всего сервиса в докере.
Иными словами, микросервисная архитектура хороша там, где у проекта много составляющих, которые делают разные люди. Каждый из них знает свою часть и может её прогнать на своём локальном компе в примитивной установке (банально curl'ом руками попинать), не пытаясь запустить весь комбайн.
Монолит практически невозможно распараллелить, то есть пилить его в два-три-четыре рыла в одном и том же куске проекта, монолит может пилить один, максимум два человека. Например, один фронтэндщик и один бэкендщик.
vmarunin
18.05.2025 10:00Так статья называется "Издержки микросервисов, которые ваш стартап может не потянуть"
Обычно это небольшой проект и там немного народу.
Да и модульный монолит вполне можно пилить человек в 5 только бэков, например, если в разных углах пилить.Frankenstine
18.05.2025 10:00Да и модульный монолит вполне можно пилить человек в 5 только бэков, например, если в разных углах пилить.
Ага, но вскоре начинаются проблемы совместимости разных третьесторонних модулей, потому что Вася использует приблуду завязанную через зависимости на некий плагин энной ветки, а Петя ветки эн плюс эм, и в зависимости от версии, впиленной в монолит, не работает либо Петин код, либо Васин :)
Или другой вариант - скажем, код Пети работает на nodejs v.18 и ниже, а код Васи не может работать ниже чем на nodejs v.20, и либо Пете надо переписывать почти весь свой код, либо Васе нужно придумывать костыли...
vmarunin
18.05.2025 10:00А как они затащат этот модуль?
Вот есть монолит, есть сборка.
Если какой-то пакет что-то обновляет, то либо оно обновится, либо накроется тестами.
Версия ноды тоже получается из процесса сборки.
Как они затащат разные модули? Первый успеет, а второй будет страдать.
А если уж есть компилятор (Go, Java, C#), то там оно или соберётся и можно работать, или не соберётся.
Opaspap
18.05.2025 10:00Тоже хотел сказать, что оркестрацией почти все проблемы из таблички решаются просто запретом ручного деплоя и как следствие - использованием чего то типа k8s и прочих терраформеров.
Кстати никто ге мешает сделать вариант композа удобного для локальной разработки и конфигов для энтерпрайзы, особенно если деплой идет через ci всегда.
apcs660
18.05.2025 10:00Верно замечено... Конечно, в монолите можно культурно обработать ошибки (сохранить ошибку на стартапе к примеру, и описать причину во время запроса) но самая главная проблема связана с падением процесса. К примеру, ООМ в Java приложении или ошибка JVM - это не лечится. Память заранее не обсчитать (можно конечно оценку сделать но во первых Java и так тормозная, а во вторых, в многопоточном приложении это тяжело делать). Вспоминаешь С, Objective C - там с оценкой расхода памяти было попроще...
Особенно проблема усугубляется когда код интенсивно использующий ресурсы, интегрируют с фасадом взаимодействующим с пользователем.
Был проект zero footprint viewer, там рендеринг запаковали в web war, хотя по хорошему его как раз нужно выносить наружу в ферму сервисов рендереров.
Пытались разрулить нагрузку балансером запросов но это не помогало если пришел к примеру документ "бомба" который ест CPU (привет, веб таймат!) или память (привет, ООМ!).
У меня разок еще поисковик у клиента подвисал и терял сессию - оказалось запрос на поиск шел 20 минут. Стал копать - виртуальная машина перегружена, диск I/O реально было 30 МБ/сек и поиск шел 20 минут. На тестовом стенде с SSD, тот же поиск занял 1.5 сек. Это самый тяжелый запрос был с полным сканированием, первый холодный поиск.
kekoz
18.05.2025 10:00Если бы создатели StackOverflow считали микросервисы “правильным путем”, у нас бы не было StackOverflow. Как один из примеров, что у всех на виду.
apcs660
18.05.2025 10:00наверное нужно все в меру использовать. Щепотка соли это улучшение вкуса, а столовая ложка за раз - смерть.
Микросервисы хороши для динамического управления произовидительностью и защиты от падения (чтобы все не легло). Там где нагрузка может привести к падению процесса, лучше его выделить в сервис.
В "он премисис", где бюджет заложен жестко, бывает проще руками настроить все один раз и не трогать (несколько больших производительных монолитов).
Как только вводишь новую технологию, это подразумевает вопрос клиента "кто будет поддерживать?", приходится работать с тем стеком и специалистами, которые есть.
К8S? кто будет его поддерживать? Еластик? У нас есть Солр, давайте с ним же. и тд и тп.
"Делая большие дела, не забывай о малых, но умей расставлять приоритеты".
kekoz
18.05.2025 10:00До того как начать что-то использовать в меру, необходимо усвоить ещё более важные принципы — не охотиться с мортирой на воробьев, не забивать микроскопом гвозди, не использовать что бы то ни было только потому, что “ну, раз оно есть, то надо заюзать” или “а чтоб было!”, и т.д. Убеждён, если бы все так поступали, микросервисных поделок было бы на порядки меньше. K8s для какой-нибудь тудушки на пару сотен юзеров — это даже не смешно, это микросервис головного мозга в терминальной стадии.
Кстати, из опыта того же StackOverflow -- там, где нагрузка может привести к падению процесса (справедливости ради — это везде :), в первую очередь надлежит не об отдельном сервисе задумываться, а убедиться в обеспеченности этого процесса ресурсами. Их главная инженерка прямо отметила, что поставить на машину с PostgreSQL терабайт RAM оказалось решением куда более простым и эффективным, чем вся так микросервисная фигня, которая частенько взбредает в головах “молодых да буйных”.
apcs660
18.05.2025 10:00Аналогично с индексами - не зная какой будет поиск, ставят не глядя кластер на пяток нодов, включают реплицирование, создают под сотню шардов и выясняется в проде что join не работает либо медленнее в сто раз и проще было бы отклонировать вертикально масштабированные 3 сервера с одним шардом в каждом. Потому что 50 шардов с примерно 10 млн доков в каждом для join категорически не подойдут - коммуникация между нодами сжирает время. Wildcard запросы да, быстрее будут.
Бывает так что архитектура выбирается для портфолио - модно, сковородно, хорошо для резюме.
S1908
18.05.2025 10:00Две стороны монеты:
Если монолитим то все останется монолитом так как на микросервисы не останется времени. В итоге огромный монолит с концентрованной сложностью в будущем. В итоге проект становится скучным не технологичным.
Если микросервисим то да вначале все трудно границы до конца неизвестны, но в будущем все становится кирпичиками модулями которых легко компоновать и переносить между проектами.
Dhwtj
Недешёвый инструмент управления сложностью и чуть чуть масштабируемостью