CQRS и event sourcing
Тема дорожной карты · Backend разработчик
CQRS (Command Query Responsibility Segregation) — архитектурный паттерн, разделяющий сторону записи (команды, изменяющие состояние) и сторону чтения (запросы, возвращающие данные) на отдельные модели, что позволяет масштабировать, оптимизировать и развивать каждую из них независимо. На стороне команд входящие запросы проверяются и диспетчируются как неизменяемые объекты команд — нередко через брокер сообщений Kafka или RabbitMQ — и обрабатываются доменными агрегатами по принципам DDD, что делает CQRS естественным компаньоном для DDD и микросервисов. Сторона чтения поддерживает одну или несколько денормализованных таблиц проекций (или специализированных хранилищ чтения, таких как Elasticsearch или Redis), обновляемых посредством потребления доменных событий, что обеспечивает субмиллисекундную задержку запросов даже под высокой нагрузкой. Реализация CQRS в сервисе на Spring Boot обычно включает отдельные бины @CommandHandler и @QueryHandler, соединённые через фреймворк наподобие Axon, тогда как в Node.js-стеке аналогичное разделение достигается с помощью библиотек event sourcing совместно с PostgreSQL для модели записи и Redis для кеша чтения. Поскольку CQRS вводит итоговую согласованность между командной и запросной плоскостями, паттерн лучше всего подходит для сложных, высоконагруженных доменов, где рабочие нагрузки на чтение и запись существенно различаются.
Как это работает
CQRS и event sourcing имеет варианты: монолит (один деплоябл, простой ops, тяжело масштабировать команды за ~30 инженеров), modular monolith (один деплоябл, внутренние границы модулей, масштабируется намного дальше, чем считают), микросервисы (много мелких сервисов, сложный ops, масштабирует команды). Паттерны: hexagonal / clean architecture (отделить домен от инфры), CQRS (раздельные read + write модели), event sourcing (state из event log), domain-driven design (моделируем бизнес). "Правильная" архитектура — простейшая, решающая текущие ограничения.
Когда применять
Каждый новый проект — modular monolith. Разделяйте на сервисы только когда (а) в команде > ~30 инженеров, (б) у одного компонента сильно другие требования к масштабу, (в) регуляторные границы требуют изоляции. "Архитектура" — это в основном про что вы можете дёшево менять потом; принимайте решения, откладывающие необратимость (БД на сервис — очень необратимо; границы модулей в монолите — дёшево перерисовать).
Типичные ошибки
Ловушки CQRS и event sourcing: микросервисы для 5-инженерной команды (каждый сервис стоит ops + observability; больше дебажите RPC, чем шипите фичи); погоня за паттернами из FAANG-блогов на startup-масштабе (их ограничения не ваши); переписывание "ради clean architecture" без замеренной выгоды (clean ≠ better — только если окупается в изменяемости). Оптимизируйте под следующие 12 месяцев, не под 10x масштаб, которого нет.