← все статьи
7 мин

Монолит не умер. Вы просто плохо его написали

В 2015 году все разбивали монолиты на микросервисы. В 2020-м начали писать о "modular monolith". Сейчас – снова пишут про "return to monolith". Маятник качается, а суть не меняется: архитектура должна соответствовать задаче, а не тренду.

Что не так с микросервисами по умолчанию

Микросервисы решают реальные проблемы: независимый деплой, масштабирование отдельных компонентов, изоляция отказов, независимые команды. Но всё это имеет цену, которую часто недооценивают на старте.

  • Сетевые вызовы вместо функций – latency, retry, circuit breaker
  • Распределённые транзакции – saga pattern вместо BEGIN/COMMIT
  • Observability с нуля – трейсинг между сервисами, distributed logging
  • Отладка – воспроизвести баг локально становится задачей на полдня
  • Версионирование API между сервисами – backward compatibility навсегда

Для команды из 3-5 человек на раннем продукте – это всё overhead, который замедляет разработку в несколько раз.

Хорошо написанный монолит

Проблема не в монолите как архитектуре – проблема в монолите без внутренних границ. "Big ball of mud" – это не монолит, это отсутствие архитектуры.

Modular monolith – монолит с чёткими внутренними модулями, каждый из которых имеет явный публичный API. Модули не обращаются к базе данных друг друга напрямую. Зависимости – только через интерфейсы.

// Плохо – модуль Orders знает про таблицу users const order = await db.query(` SELECT o.*, u.email FROM orders o JOIN users u ON u.id = o.user_id WHERE o.id = $1 `, [orderId]); // Хорошо – Orders вызывает UsersModule через интерфейс const user = await usersModule.getUserById(order.userId); const order = await ordersModule.getOrder(orderId);

Признаки, что пора делить

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

// разные требования к масштабированию

Если один компонент (например, генерация отчётов) потребляет в 50 раз больше ресурсов, чем остальные – имеет смысл вынести его отдельно. Не весь монолит, а конкретный bottleneck.

// независимые команды

Если над разными частями продукта работают отдельные команды с разным release cadence – монолит создаёт coordination overhead. Но это проблема возникает при 15+ инженерах, не при 5.

// разные требования к надёжности

Платёжный сервис и сервис уведомлений – разные SLA, разные требования к безопасности, разные on-call процедуры. Изоляция оправдана.

Стратегия

Начните с монолита. Пишите его модульно – чёткие границы, никаких "заглядываний" в чужие данные. Когда появится конкретная боль (не теоретическая, а настоящая) – вырежьте сервис по уже готовой модульной границе. Это займёт неделю, а не месяц.

Если вы не можете написать хороший монолит, вы не напишете хорошие микросервисы. Вы просто распределите плохой монолит по сети.


← все статьи Следующая →Внутренняя команда vs. внешний архитектор