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

Обновлено:

Для стартапа, инди-хакера или небольшой команды ответ однозначный: начинайте с монолита. Микросервисы — это решение для проблем большого масштаба, которых у вас ещё нет. Разберём почему, и когда это правило стоит нарушить.


Что такое монолит и что такое микросервисы

Монолит

Монолитное приложение — это единый деплоируемый юнит. Вся бизнес-логика, API, фоновые задачи и UI (если есть) живут в одном кодовом репозитории и деплоятся вместе.

myapp/
├── api/
│   ├── users.py
│   ├── products.py
│   └── orders.py
├── services/
│   ├── email_service.py
│   └── payment_service.py
├── models/
│   ├── user.py
│   ├── product.py
│   └── order.py
├── workers/
│   └── background_tasks.py
└── main.py

Один процесс, одна база данных, один деплой.

Микросервисы

Микросервисная архитектура — это набор независимых, слабо связанных сервисов, каждый из которых:

  • Имеет свою базу данных
  • Деплоится независимо
  • Общается с другими через API или message broker (RabbitMQ, Kafka)
  • Разрабатывается и масштабируется независимо
services/
├── user-service/          # Python FastAPI, PostgreSQL
├── product-service/       # Go, MongoDB
├── order-service/         # Java, MySQL
├── notification-service/  # Node.js, Redis
└── api-gateway/           # Nginx + routing

Почему стартапу нужен монолит

Аргумент 1: Скорость разработки — это ваш главный актив

На ранней стадии стартапа главная задача — найти Product-Market Fit. Это требует быстрых итераций: запустили фичу, получили фидбек, изменили, запустили снова.

В монолите изменение функции заказов затрагивает один файл и один деплой. В микросервисах — нужно изменить API-контракт, обновить order-service, обновить api-gateway, проверить совместимость с product-service, синхронизировать версии.

Аргумент 2: Инфраструктура микросервисов стоит дорого

Микросервисы требуют заметно больше инфраструктуры, чем монолит при той же нагрузке: отдельные среды, оркестрация, межсервисная коммуникация и наблюдаемость. Для стартапа это прямые деньги из бюджета — ещё до появления первого платного пользователя.

Что нужно для микросервисов:

  • Kubernetes или аналог (оркестрация)
  • Service Mesh (Istio, Linkerd) для коммуникации
  • Распределённое логирование (ELK Stack или Loki)
  • Distributed tracing (Jaeger, Zipkin)
  • API Gateway
  • Message Broker (Kafka, RabbitMQ)
  • Отдельные CI/CD пайплайны для каждого сервиса
  • DevOps-инженер, который всё это поддерживает

Всё это — до того, как у вас появился первый платный пользователь.

Аргумент 3: Распределённые системы — это сложно

В монолите: вызвать функцию = 0мс, всегда успешно. В микросервисах: HTTP-запрос к другому сервису = 1-10мс, может упасть, может timeout, может вернуть устаревшие данные.

Проблемы, которые появляются только в микросервисах:

  • Частичный отказ (один сервис упал, другие работают)
  • Распределённые транзакции (как отменить заказ, если payment-service упал после списания?)
  • Eventual consistency (данные в разных сервисах могут быть рассинхронизированы)
  • Версионирование API между сервисами
  • Дедлоки через network calls

Аргумент 4: Часть команд возвращается к монолитам

Известны публичные истории команд, которые начали с микросервисов, столкнулись с операционной сложностью и стоимостью и консолидировали сервисы обратно в монолит или модульный монолит. Крупные компании вроде Amazon, Netflix и Uber перешли на микросервисы, уже имея тысячи инженеров, а не сотни пользователей.


Модульный монолит: лучшее из двух миров

Модульный монолит — это монолит с чёткими внутренними границами между компонентами. Он даёт скорость монолита и готовность к декомпозиции при необходимости.

Как выглядит модульный монолит

# Модуль Users
# users/models.py, users/service.py, users/api.py

# Модуль Orders
# orders/models.py, orders/service.py, orders/api.py

# Модули НЕ обращаются напрямую к моделям друг друга
# Только через публичные интерфейсы (service functions)

# ПЛОХО: прямой доступ к модели другого модуля
from orders.models import Order  # из users/

# ХОРОШО: через сервисный слой
from orders.service import get_user_orders  # Публичный API модуля

Пример структуры на FastAPI

# app/modules/users/
#   models.py     — User SQLModel
#   service.py    — create_user, get_user, update_user
#   api.py        — FastAPI router
#   events.py     — события (UserCreated, UserUpdated)

# app/modules/orders/
#   models.py     — Order SQLModel
#   service.py    — create_order, cancel_order
#   api.py        — FastAPI router
#   events.py     — OrderCreated, OrderCancelled

# app/modules/payments/
#   service.py    — process_payment, refund
#   api.py

# main.py — собираем всё вместе
from app.modules.users.api import router as users_router
from app.modules.orders.api import router as orders_router
from app.modules.payments.api import router as payments_router

app = FastAPI()
app.include_router(users_router, prefix="/users")
app.include_router(orders_router, prefix="/orders")
app.include_router(payments_router, prefix="/payments")

Такая архитектура: один деплой, одна БД, но чёткие границы. Когда вырастете — «отпилить» payments в отдельный сервис будет несложно.


Когда переходить на микросервисы

Реальные триггеры, а не теоретические:

Триггер 1: Команда мешает друг другу

Когда 3+ команды работают над одним репозиторием и постоянно конфликтуют при мерджах, тормозят деплой друг друга — это сигнал. Обычно это происходит при 20-50+ инженерах.

Триггер 2: Один компонент убивает всё

Например, тяжёлые вычисления (ML-обработка, конвертация видео) потребляют весь CPU и роняют API. Этот компонент стоит выделить в отдельный сервис с независимым масштабированием.

API (5 инстансов, 1 CPU) + Video Processing (2 инстанса, 16 CPU)
vs.
Монолит (7 инстансов, 17 CPU каждый) — неэффективно

Триггер 3: Разные технические требования

Если часть системы должна быть на Python (ML), часть на Go (high-performance API), часть на Node.js (real-time WebSocket) — микросервисы позволяют использовать правильный инструмент для каждой задачи.

Триггер 4: Изоляция критичных данных

Платёжные данные требуют PCI DSS compliance? Медицинские данные требуют HIPAA? Выделение в отдельный сервис упрощает аудит и compliance.


Практическое сравнение

| Критерий | Монолит | Микросервисы | |---|---|---| | Скорость разработки | Высокая | Низкая (особенно начало) | | Сложность деплоя | Низкая (один деплой) | Высокая (N деплоев) | | Отладка | Простая (один лог) | Сложная (distributed tracing) | | Стоимость инфраструктуры | Низкая | Заметно выше | | Масштабирование | Вертикальное / горизонтальное всего | Независимое для каждого сервиса | | Команда | 1-15 человек | 20+ человек | | Транзакции | ACID через ORM | Сложные (saga, two-phase commit) | | Время до первого деплоя | Минуты | Дни-недели | | Подходит для | Стартапы, MVP, инди-хакеры | Крупные компании, после PMF |


Реальные примеры

Истории успеха монолитов

  • Basecamp — прибыльный SaaS на Rails, построенный как монолит
  • GitHub — долго был монолитом (Rails), перешёл на частичную декомпозицию только после многих лет
  • Shopify — крупный модульный монолит на Rails, выдерживающий высокую нагрузку
  • Stack Overflow — долгое время обслуживал большую аудиторию на небольшом числе серверов

Когда микросервисы оправданы

  • Netflix — сотни и тысячи микросервисов, большой штат инженеров, уникальные требования к масштабированию
  • Amazon — декомпозиция по командам («pizza team»)
  • Uber — географически распределённые операции с разными требованиями

Заметьте: все эти компании начали как монолиты.


Micro-SaaS: особый случай

Micro-SaaS — это маленький SaaS-продукт, решающий узкую задачу для нишевой аудитории. Обычно делается одним человеком (солопринером) или маленькой командой.

Для micro-SaaS ответ ещё более однозначен: монолит, и желательно максимально простой.

Идеальный стек для micro-SaaS в 2026:

  • Django + PostgreSQL (или FastAPI + SQLModel)
  • SQLite для начала (быстрый старт, одна команда деплоя)
  • Railway или Render для хостинга (без DevOps)
  • Stripe для платежей

Никаких Kubernetes, никакого Kafka, никаких микросервисов.


Когда начать думать о декомпозиции

Признаки, что монолит начинает мешать:

  • Сборка и тесты занимают больше 10-15 минут
  • Деплой занимает больше 30 минут
  • Добавление новой фичи требует изменений в 10+ файлах
  • Разные части системы имеют конфликтующие зависимости
  • Один компонент регулярно роняет весь сервис

Первый шаг — не микросервисы, а модульный монолит с чёткими границами.


Бэкапы в монолите: проще, чем в микросервисах

Одно из неочевидных преимуществ монолита — простота резервного копирования, и дело не только в количестве баз. У монолита одна БД, а значит один дамп — это консистентный снимок всего состояния приложения на один момент времени. pg_dump берёт MVCC-снимок без блокировки обычных чтений и записей, и внутри него данные пользователей, заказов и платежей согласованы между собой.

В микросервисах иначе: архитектура database-per-service означает, что у каждого сервиса своя БД (часто разных движков — PostgreSQL у одного, MongoDB у другого). Бэкапить нужно каждую, но куда важнее, что получить единый point-in-time снимок сразу по всем сервисам нельзя: дампы снимаются в разные моменты, а данные между сервисами связаны только через API и события. После восстановления заказ может ссылаться на платёж, которого в его дампе ещё/уже нет. Восстановление превращается в отдельную задачу: порядок, согласование версий, повтор событий. Это та же проблема распределённых данных и eventual consistency, только со стороны аварийного восстановления.

Для монолита всё сводится к одному дампу. PostgreSQL:

pg_dump "$DATABASE_URL" --format=plain --no-owner \
  --file "app-$(date +%Y%m%d_%H%M%S).sql"

SQLite (онлайн-бэкап, безопасный при включённом WAL — не обычный cp):

sqlite3 ./app.db ".backup './app-$(date +%Y%m%d_%H%M%S).db'"

Готовый дамп нужно хранить вне сервера. Сервис dbsend принимает плоские дампы pg_dump/mysqldump и файлы SQLite/DuckDB, хранит их версии с контрольной суммой SHA-256 и шлёт алерт, если бэкап не пришёл по расписанию. Сам он к базе не подключается — дамп создаёте вы (cron, CI, systemd-таймер), а CLI загружает его:

dbsend backup app-20260201_030000.sql \
  -d "$DBSEND_DATABASE_ID" -e postgresql_dump -l "nightly"

Практические рецепты — автоматические бэкапы, бэкап PostgreSQL в S3 и бэкап баз в Docker и Coolify, если сервисы живут в контейнерах.


Частые вопросы

Что делать, если я уже начал с микросервисов?

Не паникуйте. Если система ещё маленькая — рассмотрите консолидацию: объедините связанные сервисы в один. Это называется «strangler fig в обратную сторону». Если уже в продакшене с реальной нагрузкой — оцените, действительно ли декомпозиция приносит проблемы. Иногда работающая система лучше идеальной.

Монолит — это всегда спагетти-код?

Нет. Монолит может быть хорошо структурированным. Модульный монолит с чёткими границами между модулями — это не спагетти. Спагетти-код — это проблема дисциплины, а не архитектуры.

Можно ли начать с монолита и потом перейти на микросервисы?

Да, и это стандартный путь. Ключ — проектировать монолит с чёткими модульными границами с самого начала. «Отпилить» хорошо изолированный модуль несложно. Распутать настоящее спагетти — задача на месяцы.

Serverless — это микросервисы?

Serverless (AWS Lambda, Yandex Functions) — это функции-сервисы. Концептуально близко к микросервисам, но ещё более атомарно. Для стартапа serverless может быть хорошим выбором для конкретных задач (обработка файлов, webhook-и), но полностью serverless-монолит (через SST, Serverless Framework) имеет свои сложности.

Netflix на микросервисах — значит, это правильный путь?

Netflix перешёл на микросервисы, имея огромную аудиторию, большой штат инженеров и уникальные требования к надёжности. Стартап с сотней пользователей — это другой контекст.

Когда микросервисы оправданы для небольшой команды?

Если у вас есть компонент с принципиально разными требованиями: например, ML-модель для обработки данных (Python, GPU) и основное API (Go, низкая латентность). Или если нужна изоляция для compliance (PCI DSS, HIPAA). Но это исключение, не правило.