CQRS: o padrão mais mal interpretado da última década

Toda vez que alguém diz que “usa CQRS”, eu faço a mesma pergunta: por quê?
Não é provocação gratuita. É curiosidade técnica legítima.
Na maior parte das vezes, a resposta vem acompanhada de um diagrama conhecido: dois bancos, uma seta indo para a direita, outra voltando, talvez uma réplica de leitura, talvez uma fila no meio. Em algum momento alguém menciona performance, escalabilidade ou “preparar o sistema para o futuro”.
O problema é simples: isso não é CQRS.
Isso é infraestrutura. E quando infraestrutura vira argumento arquitetural, o sistema começa a tomar decisões erradas com muita convicção.
CQRS não nasceu para escalar banco. Nasceu para organizar pensamento, reduzir ambiguidade e forçar clareza onde normalmente existe acoplamento disfarçado.
O erro coletivo
O erro mais comum — e mais caro — é achar que CQRS é sobre separar tabelas, schemas ou instâncias de banco. Essa separação pode acontecer, mas ela nunca deveria ser o ponto de partida.
Quando a discussão começa pelo banco, ela já começou tarde demais.
CQRS não separa dados.
CQRS separa responsabilidades semânticas.
Ele parte de uma pergunta simples, mas profundamente incômoda:
escrever e ler são realmente o mesmo problema?
Em sistemas pequenos, geralmente são. Em sistemas que cresceram, raramente continuam sendo. A partir do momento em que leitura e escrita têm ritmos diferentes, expectativas diferentes e consumidores diferentes, tratá-las como a mesma coisa vira uma forma silenciosa de dívida técnica.
O que CQRS realmente separa
CQRS significa Command Query Responsibility Segregation. O nome é direto, mas frequentemente ignorado em favor de implementações “criativas”.
Commands existem para mudar estado
Queries existem para responder perguntas
Até aqui, nada revolucionário. O detalhe está no que isso implica.
Um Command não retorna dados relevantes. Ele retorna sucesso ou falha. Ele representa uma intenção explícita de mudança e carrega consigo regras, validações e invariantes. Uma Query, por outro lado, observa o estado atual e responde algo útil para quem perguntou.
Essa separação não é técnica. É conceitual.
Ela pode existir:
no mesmo processo
na mesma aplicação
no mesmo banco
CQRS não exige microservices, event sourcing ou mensageria. Ele exige algo mais difícil: disciplina conceitual. Se você começou separando infraestrutura, provavelmente terminou sem separar responsabilidades.
Escrita como contrato
Aqui está o ponto que costuma separar times maduros de times apenas ocupados.
Um Command não é um DTO que salva algo no banco.
Um Command é um contrato.
Quando um sistema aceita um Command, ele está afirmando algo muito específico:
“Se essas condições forem verdadeiras, eu prometo que este estado será alterado.”
Isso implica validação explícita, regras claras e invariantes protegidas. Commands carregam intenção, não estrutura. Eles dizem o que o sistema aceita fazer, não como os dados serão persistidos.
Quando Commands viram apenas métodos com nomes bonitos, o domínio evapora. O sistema passa a aceitar qualquer coisa, em qualquer ordem, desde que o banco permita. Nesse ponto, não existe CQRS. Existe CRUD com uma camada extra de abstração — e nenhuma delas ajuda de verdade.
Contrato mal definido é bug futuro garantido.
Leitura como produto
Do outro lado estão as Queries. E aqui acontece o segundo grande mal-entendido.
Queries não são espelhos do domínio.
Elas não existem para serem elegantes.
Elas existem para serem úteis.
Leitura é produto. Produto muda.
Uma tela nova surge, uma decisão de negócio muda, um relatório precisa de outro formato — a leitura muda junto. E isso não é um problema. É o comportamento esperado.
Queries são:
descartáveis
moldáveis
orientadas a uso
Elas respondem perguntas específicas para consumidores específicos. Forçar leitura a respeitar o mesmo modelo da escrita é um erro clássico. É como exigir que um relatório financeiro use exatamente as mesmas abstrações internas do sistema contábil. Não é pureza arquitetural. É desperdício.
Contrato é coisa de escrita.
Leitura é adaptação.
O custo real do CQRS
CQRS não simplifica sistemas. Ele redistribui complexidade. Você troca complexidade acidental no banco por complexidade intencional no design
Essa troca custa caro.
Custa mais código, mais decisões explícitas, mais alinhamento entre pessoas. Custa conversas difíceis sobre responsabilidade, ownership e evolução. CQRS exige que o time saiba responder perguntas como: “onde essa regra vive?” e “quem é dono dessa decisão?”.
Esse custo não é um defeito. É o preço da clareza. CQRS não é um padrão para times que ainda precisam discutir onde fica a regra de negócio.
Quando CQRS faz sentido
CQRS faz sentido quando leitura e escrita evoluem em ritmos diferentes. Quando regras de negócio são críticas. Quando você precisa proteger invariantes e, ao mesmo tempo, entregar leitura rápida, flexível e orientada ao usuário.
Ele não faz sentido em CRUD simples, times pequenos ou domínios mal compreendidos. Nesses cenários, CQRS vira teatro arquitetural. E teatro não escala.
Não usar CQRS também é uma decisão arquitetural madura. A ausência consciente de um padrão costuma ser mais saudável do que sua adoção automática.
Anti-padrões comuns
Alguns sinais claros de que você não está usando CQRS, mesmo achando que está:
“Separei dois bancos, logo uso CQRS”
Commands que retornam DTOs gigantes
Queries que precisam conhecer regras de negócio
Read models sem dono claro
Times que não sabem onde uma regra deveria viver
CQRS não falha sozinho. Ele falha quando é adotado sem entendimento, apenas como resposta genérica para problemas mal formulados.
Fechando a conta
CQRS não é hype. Também não é bala de prata. É uma escolha arquitetural difícil, que exige clareza conceitual e responsabilidade organizacional.
Se parece simples, você provavelmente está ignorando o custo.
Se virou só uma separação de banco, você perdeu o ponto.
CQRS não é sobre tabelas.
É sobre intenção, contrato e leitura como produto.
E isso, goste ou não, exige maturidade.
Se CQRS parece fácil, você não está fazendo CQRS.

