Назад к блогу

Микросервисы или монолит: когда что выбирать

Один из самых частых вопросов, который мне задают: "Стоит ли переходить на микросервисы?" Мой ответ всегда один — зависит от контекста. Расскажу о своём опыте трансформации архитектуры в финтех-проекте.

Исходная ситуация

Когда я пришёл на позицию CTO, проект представлял собой классический Laravel-монолит:

  • Одно приложение на 200+ тысяч строк кода
  • Единая база данных PostgreSQL
  • Всё деплоится одним релизом
  • Команда из 8 разработчиков

Монолит работал, но появились проблемы:

  1. Долгие релизы — деплой занимал 40+ минут с даунтаймом
  2. Конфликты при разработке — команды мешали друг другу
  3. Сложность тестирования — прогон всех тестов занимал 2 часа
  4. Точечное масштабирование невозможно — нагрузка на скоринг не связана с нагрузкой на личный кабинет

Что НЕ стоит делать

Первый порыв — "давайте всё перепишем на микросервисы!" Это путь в никуда. Вот что я понял на своих ошибках:

Не дробите на микросервисы сразу — сначала поймите границы доменов

Не выбирайте технологии ради хайпа — Kubernetes для трёх сервисов это оверкилл

Не игнорируйте команду — микросервисы требуют другой культуры разработки

Наш подход: постепенная декомпозиция

Мы выбрали стратегию "Strangler Fig Pattern" — постепенное выделение сервисов из монолита.

Шаг 1: Выделение скоринга

Первым кандидатом стал модуль скоринга — он имел чёткие границы и высокую нагрузку:

┌─────────────────────────────────────────┐
│              Монолит                    │
│  ┌─────────┐  ┌─────────┐  ┌─────────┐ │
│  │  Users  │  │  Loans  │  │ Scoring │ │
│  └─────────┘  └─────────┘  └────┬────┘ │
└────────────────────────────────┼───────┘
                                 │
                                 ▼
┌─────────────────────────────────────────┐
│              Монолит                    │
│  ┌─────────┐  ┌─────────┐              │
│  │  Users  │  │  Loans  │──────────┐   │
│  └─────────┘  └─────────┘          │   │
└────────────────────────────────────┼───┘
                                     │
                    ┌────────────────▼───┐
                    │   Scoring Service  │
                    │   (Python + ML)    │
                    └────────────────────┘

Шаг 2: API Gateway

Для маршрутизации запросов внедрили простой API Gateway на базе nginx:

upstream scoring {
    server scoring-service:8000;
}

upstream monolith {
    server monolith:80;
}

location /api/v1/scoring {
    proxy_pass http://scoring;
}

location / {
    proxy_pass http://monolith;
}

Шаг 3: Асинхронное взаимодействие

Для обмена данными между сервисами внедрили RabbitMQ:

// В монолите — публикация события
class LoanCreatedEvent implements ShouldBroadcast
{
    public function __construct(
        public readonly int $loanId,
        public readonly int $userId,
        public readonly float $amount
    ) {}

    public function broadcastOn(): string
    {
        return 'loans';
    }
}

// Публикация
event(new LoanCreatedEvent($loan->id, $loan->user_id, $loan->amount));
# В скоринг-сервисе — подписка
@app.on_event('loans.loan_created')
async def handle_loan_created(event: LoanCreatedEvent):
    score = await calculate_score(event.user_id)
    await publish('scoring.score_calculated', {
        'loan_id': event.loan_id,
        'score': score
    })

Шаг 4: Независимые базы данных

Каждый сервис получил свою базу данных:

# docker-compose.yml
services:
  postgres-main:
    image: postgres:15
    environment:
      POSTGRES_DB: monolith

  postgres-scoring:
    image: postgres:15
    environment:
      POSTGRES_DB: scoring

Результаты через год

После выделения 4 сервисов (скоринг, уведомления, отчёты, интеграции):

МетрикаБылоСтало
Время деплоя40 мин5 мин (per service)
Прогон тестов2 часа15-20 мин (параллельно)
Время на онбординг2 недели3-4 дня (один сервис)
Аптайм99.5%99.95%

Когда микросервисы НЕ нужны

На основе опыта, микросервисы не нужны если:

  • Маленькая команда (< 5 человек) — накладные расходы съедят всю пользу
  • Стартап на ранней стадии — сначала найдите product-market fit
  • Нет DevOps-экспертизы — микросервисы требуют зрелой инфраструктуры
  • Нечёткие границы доменов — получите распределённый монолит

Выводы

  1. Монолит — это нормально. Начинайте с монолита, выделяйте сервисы по мере необходимости
  2. Выделяйте по границам домена. Не по техническим слоям (фронт/бэк/БД), а по бизнес-логике
  3. Инвестируйте в инфраструктуру. CI/CD, мониторинг, логирование — без них микросервисы превращаются в ад
  4. Команда важнее архитектуры. Лучше сильная команда с монолитом, чем слабая с микросервисами

Микросервисы — это инструмент, а не цель. Используйте его когда он решает реальные проблемы, а не создаёт новые.