Во многих системах одна модель данных обслуживает всё сразу: создание заказа, изменение статуса, список заказов, отчёты и поиск.
Пока продукт небольшой, это удобно. Но по мере роста требования к записи и чтению начинают расходиться.
Запись должна строго соблюдать бизнес-правила. Чтение хочет быть быстрым и подготовленным именно под конкретный сценарий.
Какую проблему мы решаем
CQRS — Command Query Responsibility Segregation — разделяет операции изменения состояния и операции чтения.
Это не обязательно две физические базы. Суть в том, что модели и пути обработки могут быть разными.
Команда может строить строгую модель для команд и отдельные представления для чтения, оптимизированные под экраны, поиск или отчёты.
Что получает бизнес
Главная выгода появляется, когда тяжёлое чтение начинает мешать рабочим операциям или когда новые интерфейсы слишком дорого собирать из основной модели.
Разделение позволяет независимо ускорять пользовательские экраны, отчёты и поиск, не усложняя при этом правила записи.
Это может сокращать стоимость новых представлений данных: вместо изменения сложного ядра продукта команда создаёт отдельную read-модель под конкретный сценарий.
Но бизнес получает выгоду только при достаточной сложности. В простой системе CQRS способен увеличить стоимость разработки без заметного результата.
Что получает команда
Команда может отдельно моделировать команды и запросы, независимо масштабировать чтение и использовать денормализованные представления.
Взамен появляются синхронизация моделей, дополнительные обработчики и необходимость понимать, насколько быстро read-модель должна догонять изменения.
Что получает клиент
Клиент может получить более быстрые списки, поиск и сложные представления без того, чтобы аналитические запросы тормозили основные операции.
Но иногда изменения становятся видны не мгновенно. Пользователь сохранил данные и через короткий момент read-модель ещё показывает предыдущую версию.
Чем мы за это платим
Цена — дублирование моделей и eventual consistency.
Нужно проектировать доставку изменений, восстановление read-моделей и обработку ситуаций, когда представление отстаёт.
Отладка тоже становится сложнее: ошибка может быть не в исходных данных, а в механизме построения представления.
Когда CQRS не нужен
Если требования к чтению и записи простые и одна модель справляется без проблем, разделение почти наверняка преждевременно.
CQRS имеет смысл не как архитектурная мода, а как ответ на реальное расхождение двух типов нагрузки.
Что стоит спросить перед решением
- Действительно ли чтение и запись требуют разных моделей?
- Тормозят ли тяжёлые запросы основные операции?
- Допустима ли небольшая задержка обновления представлений?
- Сколько новых read-моделей мы реально ожидаем?
- Сможет ли команда поддерживать дополнительную сложность?
В итоге
CQRS признаёт простую вещь: данные удобнее хранить для изменений одним способом, а показывать пользователю — иногда совсем другим.
Для бизнеса смысл появляется тогда, когда это разделение ускоряет развитие продукта или снимает реальное ограничение, а не просто делает архитектуру интереснее.