Ну давай разберем. Все твердят про Event Bus, саги, outbox-паттерны, а я за 12 лет понял: половина проектов тащит шину только ради того, чтобы сказать на собеседовании «у нас CQRS». В итоге — распределенный ад, дедлоки и саги, которые висят неделями. Вопрос простой: кто-нибудь пробовал честный CQRS без шины, когда команды пишут в основную БД, а read-модель обновляется синхронно в той же транзакции? Да, теряем асинхронность, но получаем консистентность и отладку без боли.
Я уже год так делаю на проекте с высокой нагрузкой на чтение и редкими записями. Никаких очередей, никаких повторных доставок. Read-модель — это просто денормализованные таблицы, которые обновляются в том же Unit of Work. Да, это не «истинный» CQRS по Эвансу, но работает. Бенчмарки показывают, что для 95% бизнес-логики синхронное обновление быстрее и проще, чем городить огород с брокерами. Или я просто старею и не вижу смысла в сложности?
👍 1👎 1
Синхронное обновление read-модели в той же транзакции — это не ересь, это просто «материализованные вьюхи» с нормальным именованием. Ты не стареешь, ты просто перестал верить в сказки про «событийную архитектуру ради архитектуры». Для 95% CRUD-нагрузки шина — это способ развести распределённый хаос там, где хватает одного `JOIN` и пары триггеров. Особенно когда саги начинают жить своей жизнью, а outbox превращается в чёрную дыру для прод-инцидентов.
Но есть нюанс: ты теряешь не только асинхронность, но и масштабирование по записи. Если write-сторона начнёт расти, синхронное обновление денормализованных таблиц превратится в каскад блокировок. Так что твой подход — это не «истинный CQRS», а здравый инженерный компромисс. Пока требования не выходят за рамки «прочитал — записал — обновил», это лучший вариант. Когда упрёшься в партиционирование и шардирование — тогда и вспомнишь про шину. Но к тому моменту у тебя уже будет реальная боль, а не модное слово.
Согласна на все сто — это абсолютно здравый смысл, а не ересь! Я как QA, который замучился ловить «магические» баги из-за несогласованности после асинхронных событий, обеими руками за упрощение. Шина — это мощный инструмент, но когда она добавляется «на всякий случай», она превращает систему в чёрный ящик: сложно воспроизвести гонки, тяжело трейсить запрос, а тест-кейсы начинают зависеть от таймингов.
Когда команда держит CQRS в рамках одного процесса и использует синхронные команды с прямым вызовом обработчиков, я вижу только плюсы: предсказуемость, легкость в дебаге и возможность писать интеграционные тесты без моков на шину. Конечно, если у вас микросервисы или требуется масштабирование по чтению/записи независимо — тогда шина оправдана. Но для многих монолитов это просто лишний слой сложности. Так что да, давайте не плодить сущности, пока нет реального сценария! А как вы решаете проблему идемпотентности команд без шины — просто уникальными ключами или что-то хитрее?