CQRS é um problema de read model, não de write model
Demos de CQRS focam em command handlers e event stores. CQRS em produção falha no lado de leitura — lag de projeção, drift semântico e consultas que ninguém projetou. O read model é a parte difícil; o write path é a fácil.
Command Query Responsibility Segregation separa escritas de leituras para que cada lado otimize de forma independente. Palestras de conferência fazem isso soar como cerimônia do lado de escrita: agregados, command buses, event stores. Incidentes de produção contam outra história. Problemas do read model em CQRS — projeções stale, drift entre verdade de comandos e tabelas de consulta, dashboards mostrando dados que contradizem o que o usuário acabou de salvar — geram os tickets de suporte. O write path costuma ser uma mutação CRUD bem testada com passos extras. O read path é um warehouse desnormalizado sem dono, atualizado assincronamente por um worker de projeção que ficou para trás durante o deploy.
Equipes que adotam CQRS dividindo o write model primeiro herdam consistência eventual sem projetá-la. Obtêm dois bancos de dados, um event bus, e lag medido em segundos que vira minutos sob carga — sem reconciliação, sem contrato de frescura, e sem resposta quando um usuário pergunta "por que minha mudança não aparece?"
O CQRS do lado de escrita é o que as equipes já sabem fazer
O write model em CQRS é lógica de domínio que a equipe já escrevia — encapsulada em agregados ou serviços, validada, persistida. Adicionar commands e events muda o transporte, não a dificuldade fundamental. A maioria das regras de negócio já vivia no write path: invariantes, autorização, validação.
A parte sedutora é a pureza arquitetural. Renomear updateOrder para ShipOrderCommand, emitir OrderShipped, sentir-se maduro. O read model é adiado: "vamos projetar para uma tabela de consulta depois." Depois chega quando o primeiro dashboard lê de orders_view que está três segundos atrás de orders e suporte abre um bug que não se reproduz no write side.
CQRS sem estratégia de read model são dois bancos de dados e uma prece.
Consistência eventual não é um delay fixo. Sob carga normal, lag de projeção pode ser 50 ms. Sob deploy, rebalanceamento de broker ou reinício do worker de projeção, lag se estende a segundos ou minutos. O sistema promete consistência eventualmente — não quando. Consumidores que assumem frescura — humanos atualizando uma página, agentes lendo estado para decidir a próxima ação — quebram em silêncio.
O read model define para que serve CQRS
O read model existe porque consultas têm forma distinta das escritas. Um write armazena linhas de pedidos normalizadas. Um read precisa de user_orders_view com nome do cliente, títulos de itens e status pré-joinados — zero joins em tempo de consulta, leituras sub-milissegundo ao custo de atualizações assíncronas.
Projetar o read model significa responder perguntas que o write model não faz:
- Quais consultas o produto executa? Vistas de lista, páginas de detalhe, busca, agregações, exports — cada uma pode precisar de uma projeção distinta.
- Qual staleness é aceitável por consulta? Dashboard: 5 segundos pode estar ok. Confirmação de pagamento: quase zero — ler do write model ou projeção síncrona.
- Quem é dono da correção de projeções? Quando
orders_view.totaldiscrepa deorders.total, qual é verdade e quem corrige o pipeline? - Como o drift é detectado? Jobs de reconciliação comparando estado do write side com projeções em schedule — não descoberto por usuários.
| Superfície de consulta | Tolerância de staleness | Read path |
|---|---|---|
| Dashboard admin | 1–5 segundos | Tabela de projeção |
| Histórico de pedidos do cliente | < 1 segundo | Projeção com monitor de lag |
| Recibo de pagamento | Zero | Write model ou read síncrono |
| Índice de busca | 10–60 segundos | Projeção async + rebuild |
| Consulta de ferramenta de agente | Depende de autonomia | Contrato de frescura requerido |
O padrão de event sourcing sem cerimônia cobre logs append leves com projeções inline. CQRS completo adiciona múltiplos read models por write stream — cada um uma decisão de produto, não um default de framework.
Lag de projeção é bug de correção, não métrica de performance
Equipes monitoram lag de offset do broker e chamam de saudável a 10.000 eventos atrás. Usuários chamam de quebrado quando sua atualização não aparece. Importam métricas de lag com significado de negócio: "delay de visibilidade de pedidos p99 em segundos," "frescura do índice de busca," "idade de dados do dashboard."
Modos de falha:
Desaceleração gradual. O worker de projeção processa menos eventos por segundo do que o write side produz. Lag cresce de segundos a horas antes de alguém notar. O read model está materialmente incorreto; recuperar leva mais do que stakeholders toleram.
Eventos veneno. Um evento malformado derruba o handler de projeção. Processamento para. Write side continua. Divergência se compõe.
Drift semântico. Write model evolui — campos novos, status renomeados. Código de projeção fica para trás. Read model fala idioma distinto do command side. Não desacordo de timing — desacordo de significado.
Jobs de reconciliação reparam drift: comparar verdade do write side com estado de projeção, emitir correções, alertar em mismatch. Construa reconciliação antes do primeiro incidente, não depois. O padrão é o mesmo que logs append de event sourcing — verdade de um lado, estado derivado do outro, caminho de reparo explícito.
CQRS e agentes de IA quebram com leituras stale
Agentes autônomos leem estado, decidem, agem, leem de novo. Consistência eventual transforma o loop em drift de contexto: o agente age sobre dados stale, observa dados stale novamente, replaneja incorretamente, queima tokens em ações contraditórias. Humanos atualizam e esperam. Agentes confiam no que leem.
Read models orientados a agentes precisam de contratos de frescura explícitos:
- Retornar timestamp
projected_atcom cada resposta de consulta. - Rejeitar ou marcar leituras quando lag excede limiar para workflows autônomos.
- Rotear consultas de agente de alto risco ao write model ou path síncrono.
CQRS para dashboards humanos tolera segundos de lag. CQRS para orquestração de agentes sem garantias de frescura é um acidente esperando um trace de produção.
Quando CQRS justifica a complexidade do read model?
Essas perguntas determinam se CQRS ganha seu custo operacional para um bounded context.
Este bounded context deveria usar CQRS?
CQRS se justifica quando perfis de carga de leitura e escrita divergem fortemente — muitas leituras por escrita, joins custosos, múltiplas formas de consulta sobre os mesmos dados — e quando a equipe pode aceitar consistência eventual para a maioria das consultas com exceções explícitas. Pule CQRS quando padrões de leitura e escrita são similares, quando consistência forte é requerida em todos os lugares, ou quando a equipe não tem capacidade para ser dona de projeções e reconciliação.
Quantos read models são suficientes?
Um read model por padrão de consulta distinto — não um por tela. order_list_view e order_detail_view podem fundir se a vista de detalhe é lookup por chave na mesma tabela desnormalizada. Índices de busca, agregados analíticos e formatos de export são read models separados com contratos de staleness separados.
O que acontece quando projeção e write model discordam?
O write model vence. Projeções são derivadas e reparáveis. Execute reconciliação, identifique a fonte de divergência, replay de eventos se necessário, corrija código de projeção, documente o incidente. Nunca "corrija" o write model para coincidir com uma projeção stale. O monolito modular pode hospedar CQRS dentro de limites de módulo antes da rede multiplicar lag e domínios de falha.
Um argumento comum vai na outra direção
A visão oposta sustenta que CQRS é over-engineering — que read replicas, materialized views e caching resolvem escalonamento de leitura sem modelos separados de command e query.
Read replicas e materialized views funcionam para muitos sistemas. CQRS agrega valor quando múltiplos read models heterogêneos devem evoluir independentemente de um write stream, quando replay de eventos deve reconstruir projeções após mudanças de lógica, ou quando escalonamento de escrita e leitura requer tecnologias de armazenamento distintas. O erro é aplicar CQRS por arquitetura orientada ao currículo quando read replicas de Postgres bastariam.
Key takeaways
- Falhas de CQRS em produção são falhas de read model: lag, drift, reconciliação faltando.
- Projete read models primeiro — formas de consulta, contratos de staleness, ownership.
- Lag de consistência eventual é ilimitado sob carga; monitore frescura com significado de negócio.
- Jobs de reconciliação comparam verdade do write com projeções antes de usuários encontrarem drift.
- Consumidores agente precisam de metadata de frescura; leituras stale causam erros autônomos.
- Cerimônia do write side é fácil; operações do read side são onde CQRS vive ou morre.
Conclusion
Treinamento em CQRS enfatiza commands. Operações de CQRS enfatizam projeções. Equipes que têm sucesso começam com as consultas que seu produto realmente executa, definem quão stale cada resposta pode ser, e constroem reconciliação antes do worker de projeção ficar para trás pela primeira vez.
A pergunta da revisão arquitetural não é "devemos separar leituras e escritas?" É "quais read models precisamos, quem é dono, e o que acontece quando mentem?" Responda isso antes de dividir o write path. O write side nunca foi a parte difícil.