Монолит или микросервисы для веб-приложения: как выбрать архитектуру

Каждый год тысячи команд задают один и тот же вопрос перед стартом разработки веб-приложения: монолит или микросервисы? Мартин Фаулер, один из ведущих архитекторов программного обеспечения в мире, сформулировал ответ ещё в 2015 году и с тех пор не изменил позиции: «Не начинайте новый проект с микросервисов, даже если уверены, что приложение достаточно вырастет, чтобы это окупилось». Эту точку зрения подкрепляет реальный кейс Amazon Prime Video: команда Video Quality Analysis перешла с микросервисной/serverless-архитектуры обратно к монолиту — и сократила инфраструктурные расходы на 90%. Это не значит, что микросервисы плохи — они великолепно работают в нужном контексте. Это значит, что монолит или микросервисы для веб-приложения — это вопрос стадии, нагрузки и команды, а не вопрос «что современнее».
В этой статье я разберу оба подхода применительно к веб-продукту — SaaS, порталу, личному кабинету, маркетплейс-бэкенду — и покажу, как принять взвешенное архитектурное решение на языке бизнеса: стоимость, сроки, риски, команда. Техническая глубина — в смежном материале; здесь — угол CEO.
Коротко: монолит или микросервисы для веб-приложения
Для нового веб-приложения ответ по умолчанию — модульный монолит. Он позволяет быстро запустить MVP, экономит бюджет на инфраструктуре и сохраняет возможность перейти к микросервисам позже — поэтапно, без переписывания с нуля. Микросервисы оправданы, когда уже есть подтверждённая нагрузка, конкретные модули требуют независимого масштабирования, а команда достаточно велика, чтобы поддерживать распределённую систему без падения скорости разработки. Переходить на микросервисы с первого дня — значит платить за сложность, которая нужна вам только потом.
Что такое монолит и микросервисы применительно к веб-приложению
Монолитное веб-приложение
Монолитная архитектура для веб-продукта — это единый деплой: фронтенд (SPA, SSR или MPA) взаимодействует с одним бэкенд-приложением, которое содержит всю бизнес-логику. Все модули — авторизация, каталог, корзина, уведомления, аналитика — живут в одном процессе и разделяют общую базу данных. Обновление приложения — это один деплой для всего сервиса.
Классические примеры веб-монолитов, которые выдержали огромную нагрузку: ранний Shopify (Rails-монолит), Basecamp, Stack Overflow (ASP.NET-монолит, обслуживающий миллионы запросов в день). Масштабирование монолита — горизонтальное: несколько идентичных инстанций за балансировщиком нагрузки.
Микросервисная архитектура веб-приложения
Микросервисы — это разбиение бэкенда на независимые сервисы, каждый из которых отвечает за один bounded context (ограниченный контекст предметной области): отдельный сервис авторизации, отдельный сервис каталога, отдельный сервис платежей. Каждый сервис имеет собственную базу данных, деплоится независимо и взаимодействует с соседями через REST, gRPC или очереди сообщений (Kafka, RabbitMQ).
Веб-фронтенд (SPA или SSR) в микросервисной архитектуре обычно не обращается к сервисам напрямую — между ними стоит API gateway или BFF (backend-for-frontend), который агрегирует данные от нескольких сервисов в один ответ.
Модульный монолит — золотая середина для веб-продукта
Модульный монолит занимает промежуточную позицию: приложение разбито на чётко разграниченные внутренние модули со строгими интерфейсами между ними, но деплоится как единое целое. Каждый модуль — это отдельная директория или пакет со своим набором сущностей, репозиториев и сервисов. Межмодульный доступ — только через явные API-контракты, не через прямые вызовы внутренних классов.
Преимущество для веб-продукта: структура кода позволяет в любой момент вынести конкретный модуль в отдельный микросервис — не переписывая, а физически разделив уже выровненные границы. Это и есть стратегия monolith-first, которую рекомендует Мартин Фаулер.
Почему новое веб-приложение почти всегда стоит начинать с монолита
Главный аргумент — YAGNI (You Aren't Gonna Need It): не строй то, что не нужно прямо сейчас. Микросервисы решают три конкретные проблемы: независимое масштабирование компонентов, независимые релизы разных команд и изоляция отказов. Если ни одной из этих проблем у вас нет — вы платите за решение несуществующей задачи.
Вторая причина — неизвестные границы сервисов. Правильно нарезать границы микросервисов можно только когда вы хорошо понимаете предметную область. На старте веб-продукта эти границы ещё не очевидны. Если нарезать неправильно — получите «распределённый монолит»: все проблемы микросервисов плюс все проблемы монолита, и ни одно из преимуществ. Фаулер называет это худшим из возможных вариантов.
Третья причина — скорость вывода MVP на рынок. Монолитное веб-приложение разрабатывается, тестируется и деплоится быстрее. Нет необходимости проектировать API-контракты между сервисами, настраивать распределённую трассировку, управлять оркестрацией контейнеров. Первая рабочая версия выходит на 30–50% быстрее — а значит, быстрее появляется обратная связь от пользователей.
Когда веб-приложению действительно нужны микросервисы
Микросервисы — не «лучшая практика по умолчанию», а инструмент для конкретных ситуаций. Переход оправдан, когда наступают следующие маркеры-триггеры:
- Независимое масштабирование отдельных модулей. Если модуль обработки медиафайлов потребляет в 20 раз больше ресурсов, чем остальной бэкенд, — выделение его в отдельный сервис позволит масштабировать только его, а не всё приложение целиком.
- Большая или распределённая команда. Закон Конвея (Conway's law) гласит: архитектура системы воспроизводит структуру команды. Когда 10+ разработчиков работают над монолитом, они начинают блокировать друг друга при мёрже и деплое. Микросервисы позволяют командам работать и релизить независимо.
- Разный релиз-цикл частей продукта. Если платёжный модуль нужно обновлять раз в неделю из-за требований регуляторов, а остальной продукт — раз в месяц, разделение позволяет деплоить их независимо без блокировок.
- Пиковый веб-трафик с явной локализацией. Новостной агрегатор с пиковыми нагрузками на поисковый сервис, маркетплейс с пиками на сервис оплаты в чёрную пятницу — там независимое масштабирование конкретного сервиса даёт реальную экономию.
- Отказоустойчивость критичных доменов. Когда падение модуля уведомлений не должно влиять на оформление заказов — изоляция сервисов даёт circuit breaker и независимый контур восстановления.
Сравнение для веб-продукта
| Критерий | Монолит (в т.ч. модульный) | Микросервисы |
|---|---|---|
| Скорость запуска MVP | Высокая — один деплой, единая кодовая база | Низкая — нужно проектировать API-контракты, настраивать инфраструктуру |
| Стоимость старта | Низкая — минимум инфраструктуры | Высокая — Docker, Kubernetes, API gateway, CI/CD на каждый сервис |
| TCO (стоимость владения) | Ниже при небольших командах и объёмах | Выше, но оправдана при большой нагрузке и команде |
| Масштабирование | Горизонтальное — реплики всего приложения за балансировщиком | Гранулярное — масштабируется только нагруженный сервис |
| Размер и структура команды | Оптимально до 5–8 человек на бэкенд | Оправданы при 10+ разработчиках, работающих на разных доменах |
| Сложность деплоя | Простой — один артефакт | Высокая — оркестрация N сервисов, версионирование API |
| Отказоустойчивость | При падении — падает всё; решается репликами | Изоляция отказов по сервисам при правильной реализации |
| Отладка и наблюдаемость | Простая — единые логи, один трейс | Сложная — нужна распределённая трассировка (Jaeger, Zipkin), агрегация логов |
| Техдолг | Накапливается внутри одной кодовой базы | Изолирован по сервисам, но умножается на число сервисов |
Как архитектура влияет на бюджет и сроки веб-проекта
Как CEO и человек, который согласовывает архитектурные решения с финансовыми реалиями проектов, я вижу это так: выбор архитектуры — это выбор структуры расходов, а не только техническое решение.
Монолит дешевле на старте по нескольким причинам. Во-первых, меньше инфраструктуры: один сервер или одна облачная инстанция вместо кластера. Во-вторых, меньше DevOps-работы: не нужен инженер, который настраивает Kubernetes, service mesh, распределённый мониторинг. В-третьих, разработчики не тратят время на проектирование API-контрактов между сервисами и синхронизацию изменений через несколько репозиториев.
Микросервисы несут скрытые затраты, которые редко учитываются в первоначальной смете:
- DevOps/инфраструктура: настройка и поддержка кластера Kubernetes, CI/CD для каждого сервиса, оркестрация деплоев — это отдельная специализация.
- Межсервисное взаимодействие: дополнительная задержка сети, необходимость обрабатывать частичные отказы, версионирование API.
- Наблюдаемость: распределённая трассировка, агрегация логов, алертинг — всё это стоит и денег, и времени.
- Тестирование: контрактные тесты между сервисами, интеграционные тесты окружений — значительно сложнее, чем тестирование монолита.
Когда переплата оправдана? Когда эти расходы ниже, чем стоимость простоя или узкого места, которое они устраняют. Высоконагруженный SaaS, где одна нагруженная компонента тормозит весь продукт — там инвестиция в микросервисы возвращается. Стартап с 50 пользователями — там эти деньги лучше потратить на рост продукта.
Кейс: как Amazon Prime Video вернулся к монолиту и сократил расходы на 90%
В мае 2023 года команда Video Quality Analysis Amazon Prime Video опубликовала разбор, который вызвал волну обсуждений в индустрии. Команда анализировала качество видеопотоков в реальном времени с помощью системы, построенной на AWS Lambda и serverless-микросервисах. После перехода на монолит инфраструктурные расходы сократились на 90%, а масштабируемость системы выросла.
Почему так произошло? Serverless-архитектура создавала огромный оверхед на передачу данных между функциями через S3. Каждый кадр видео проходил через несколько изолированных Lambda-функций с сетевыми задержками на каждом шаге. При объединении в единый процесс данные передавались в памяти — без сетевых вызовов и без лишних затрат на S3.
Вывод этого кейса не в том, что микросервисы плохи — Amazon применяет их повсеместно и успешно. Вывод в том, что микросервисы и serverless — это не universally better. Это инструмент, который решает конкретную проблему. Когда инструмент не совпадает с задачей — он создаёт издержки, а не ценность.
Как деплоят и масштабируют веб-приложение при каждом подходе
Монолит: вертикальное и горизонтальное масштабирование
Монолитное веб-приложение масштабируется двумя способами. Вертикальное масштабирование — увеличение ресурсов сервера (CPU, RAM). Работает до определённого предела и не даёт отказоустойчивости. Горизонтальное масштабирование — запуск нескольких идентичных инстанций приложения за балансировщиком нагрузки (nginx, HAProxy, AWS ALB). Это основной паттерн для продуктивных монолитов: stateless-бэкенд (состояние вынесено в Redis или в базу данных), несколько реплик, балансировщик распределяет трафик.
Статика (JS, CSS, изображения) отдаётся через CDN, снимая нагрузку с бэкенда. База данных масштабируется отдельно: реплики чтения снимают нагрузку SELECT-запросов, запись идёт на мастер. Такая схема выдерживает десятки тысяч одновременных пользователей — Stack Overflow с одним сервером бэкенда обслуживает миллионы запросов в день.
Микросервисы: контейнеризация, оркестрация, API gateway, BFF
Каждый микросервис деплоится как отдельный Docker-контейнер. Оркестрация контейнеров — Kubernetes: он управляет деплоем, масштабированием, проверками здоровья и перезапуском упавших инстанций. CI/CD-пайплайн настраивается для каждого сервиса независимо, что позволяет командам деплоить без координации друг с другом.
API gateway (Kong, AWS API Gateway, nginx) стоит перед всеми сервисами и берёт на себя аутентификацию, rate limiting, маршрутизацию запросов. BFF (backend-for-frontend) — специализированный сервис, который агрегирует данные от нескольких микросервисов и формирует ответ, оптимизированный под нужды конкретного клиента (веб-фронтенда или мобильного приложения). Через разработку API и бэкенда с продуманной архитектурой можно заложить правильные слои с первого дня.
Наблюдаемость в микросервисной архитектуре — отдельная дисциплина. Распределённая трассировка (Jaeger, Zipkin) позволяет проследить запрос через несколько сервисов. Централизованный сбор логов (ELK, Loki) агрегирует логи со всех инстанций. Метрики собирает Prometheus, визуализирует Grafana.
Путь миграции: как растить веб-приложение от монолита к сервисам
Хорошая новость: переход от монолита к микросервисам не требует переписывания с нуля. Классическая стратегия — strangler fig pattern (паттерн удавника): новый функционал разрабатывается как отдельный сервис, старый монолит постепенно «удушается» до минимума.
Практический путь для веб-приложения выглядит так:
- Выделить bounded contexts. Для начала — не деплоить отдельно, а просто разбить монолит внутри на чётко разграниченные модули. Это и есть первый шаг к модульному монолиту. Хорошие границы: модуль авторизации, модуль каталога, модуль заказов, модуль уведомлений.
- Вынести первый сервис по реальному триггеру. Когда появится конкретная причина (перегруженный модуль, отдельная команда, другой технологический стек для ML-части) — вынести этот конкретный bounded context в отдельный деплой. Не раньше.
- Разделить базы данных поэтапно. Разделение БД — самая сложная часть. Порядок: сначала логическая изоляция (отдельные схемы или префиксы таблиц), потом физическая (отдельные инстанции). Синхронизация данных на переходном периоде — через события или двойную запись.
- Добавить API gateway. Когда сервисов станет несколько — добавить единую точку входа, которая маршрутизирует трафик и централизует аутентификацию.
Ключевой принцип: каждый шаг должен быть ответом на реальную проблему, а не превентивной оптимизацией. «Мы ещё не чувствуем боли, но сделаем правильно сразу» — дорого обходится на практике.
Как выбрать архитектуру для вашего веб-приложения
Пройдите по этим вопросам — они дадут ориентир без углубления в технические детали:
- Стадия продукта. Вы запускаете MVP или развиваете зрелый продукт с подтверждённой аудиторией? Для MVP — монолит. Для зрелого продукта с болями — рассматривайте микросервисы точечно.
- Нагрузка. Есть ли у вас уже реальный трафик с узкими местами, которые нужно масштабировать независимо? Нет — монолит справится. Да, с конкретным модулем — рассмотрите его выделение.
- Размер команды. Сколько разработчиков работает на бэкенде одновременно? До 5–7 — монолит эффективнее. 10+ на разных доменах — микросервисы дают независимость.
- Требования к масштабированию модулей. Есть ли конкретные компоненты, нагрузка на которые в разы выше остальных? Если да — их стоит вынести.
- Зрелость DevOps. Есть ли в команде компетенции для поддержки Kubernetes-кластера, распределённого мониторинга и CI/CD на несколько сервисов? Нет — микросервисы создадут больше проблем, чем решат.
- Бюджет. Готовы ли вы к 30–60% надбавке к стоимости разработки и инфраструктуры на старте ради долгосрочной гибкости? Если продукт ещё не нашёл свою аудиторию — это рискованная ставка.
Если большинство ответов указывают на монолит — начните с модульного монолита и заложите правильные внутренние границы. Когда появится реальный триггер — переход будет эволюционным, а не революционным.
Спроектируем архитектуру вашего веб-приложения
Поможем выбрать между монолитом и микросервисами и построить веб-приложение, которое дёшево стартует и легко масштабируется по мере роста.
Часто задаваемые вопросы (FAQ)
Что дешевле на старте для веб-приложения — монолит или микросервисы?
На старте монолит дешевле в разы. Микросервисная архитектура требует дополнительной инфраструктуры: контейнеризация (Docker), оркестрация (Kubernetes), API gateway, отдельные CI/CD-пайплайны на каждый сервис, распределённый мониторинг. Для нового веб-приложения это лишние расходы без соразмерной пользы. Разница в стоимости старта может составлять 30–60% бюджета разработки.
Можно ли позже перейти с монолита на микросервисы?
Да, поэтапно — и это правильный путь. Стратегия называется strangler fig pattern: новые функции разрабатываются как отдельные сервисы, которые постепенно «душат» монолит, пока тот не уменьшится до минимума. Переход оправдан, когда появились реальные узкие места: конкретный модуль требует независимого масштабирования, команды мешают друг другу при деплое или разные части продукта нужно обновлять с разной частотой.
Что такое модульный монолит и чем он удобен для веб-продукта?
Модульный монолит — это единое приложение, разбитое на чётко разграниченные внутренние модули со строгими интерфейсами между ними. Развёртывается как один процесс, но внутри — как микросервисы: чистые границы, независимые домены, минимальные зависимости. Для веб-продукта это лучший из миров: простота деплоя и отладки монолита плюс структура, которая позволяет безболезненно выделить модуль в отдельный сервис по мере роста.
Нужны ли микросервисы небольшому веб-сервису или интернет-магазину?
Как правило, нет. Микросервисы оправданы, когда есть реальная потребность: независимое масштабирование отдельных модулей, команда 10+ человек, работающих над разными частями системы, или разный релиз-цикл ключевых компонентов. Небольшой интернет-магазин или SaaS-стартап с командой 3–5 человек выиграет от модульного монолита: меньше инфраструктурных расходов, быстрее разработка, проще отладка.
Как выбор архитектуры влияет на скорость разработки веб-приложения?
Монолит ускоряет разработку на старте: единая кодовая база, один деплой, простая отладка. Команда не тратит время на настройку межсервисного взаимодействия и синхронизацию API-контрактов. Микросервисы дают преимущество в скорости на зрелом продукте с большой командой: независимые релизы позволяют разным командам деплоить без блокировок. На старте, если команда небольшая, микросервисы замедляют разработку.


