Event sourcing é uma das ideias mais elegantes de arquitetura de software. Em vez de guardar o estado atual, você guarda os eventos que produziram esse estado, e o estado passa a ser uma função dos eventos.
Também é uma das que mais destroem produtividade de time quando adotada pelo motivo errado.
Já vi as duas coisas. A diferença raramente está na execução técnica.
O que ele é de verdade
Não é ter uma tabela de eventos. Isso é log append-only, que é bem mais barato e resolve a maior parte das necessidades.
Event sourcing é os eventos serem a única fonte de verdade. Não existe tabela orders com o estado do pedido. Existe uma sequência de eventos, e o pedido é o resultado de aplicá-los em ordem.
class Order {
static from(events: OrderEvent[]): Order {
return events.reduce((state, e) => state.apply(e), new Order());
}
apply(event: OrderEvent): Order {
switch (event.type) {
case "created": return this.with({ status: "pending", items: event.items });
case "paid": return this.with({ status: "paid", paidAt: event.at });
case "cancelled":return this.with({ status: "cancelled" });
}
}
}
Essa distinção é a coisa mais importante do texto. A maioria dos times que diz fazer event sourcing está fazendo log de eventos ao lado do estado, o que é uma escolha sensata e não tem nenhum dos custos que vêm a seguir.
Os custos que aparecem no mês três
Consulta. Você não consegue mais fazer select * from orders where status = 'pending'. Precisa de projeções, que são tabelas derivadas dos eventos, mantidas por processos que consomem o fluxo. Cada consulta nova pode exigir uma projeção nova, e cada projeção precisa ser reconstruível e monitorada.
Consistência eventual. A projeção fica atrás do fluxo. O usuário salva e não vê a mudança na listagem, porque a projeção ainda não processou. Isso é resolvível, com leitura do próprio fluxo depois da escrita ou com atualização otimista na interface, e é trabalho que não existiria.
Versionamento de evento. Evento é imutável e eterno. O evento pedido_criado de 2024 tem uma forma, o de 2026 tem outra, e o código precisa saber ler as duas pra sempre. Isso vira um problema de compatibilidade permanente que se acumula.
Curva de aprendizado. Todo desenvolvedor novo precisa aprender o padrão antes de fazer qualquer coisa. Em time com rotatividade, esse custo é recorrente.
Dado pessoal. Evento imutável e direito à exclusão se contradizem. A saída usual é criptografar o dado pessoal com chave por titular e jogar a chave fora, o que funciona e é mais uma peça a construir.
Os quatro casos onde vale
O histórico é o produto. Auditoria regulatória, prontuário, rastreabilidade de cadeia. Se o cliente compra a capacidade de saber o que aconteceu, event sourcing é o desenho natural em vez de um extra.
Reconstruir o passado tem valor de negócio. Poder responder “qual era o estado em 3 de março?” ou reprocessar meses de dados com uma regra corrigida. Sistema de precificação, de risco e de comissão se beneficiam muito disso.
Concorrência alta no mesmo agregado. A versão dentro do fluxo dá controle otimista natural, sem lock. Escrevi sobre a mecânica em log append-only.
Vários consumidores com visões diferentes do mesmo fato. Quando cinco áreas precisam reagir ao mesmo evento de formas distintas, o fluxo é uma boa espinha dorsal.
Os motivos ruins, que são os mais comuns
“Vamos precisar de auditoria.” Log append-only ao lado da tabela de estado resolve, com um décimo do custo.
“Escala melhor.” Não necessariamente. Escala diferente, com mais peças pra operar.
“É mais moderno.” Esse é o motivo real em boa parte dos casos, e ninguém diz em voz alta.
“Já usamos Kafka.” Ter um broker não é fazer event sourcing. São coisas independentes.
O caminho do meio, que é o que eu recomendo
Guarde os eventos. Guarde também o estado.
-- estado, do jeito que sempre foi. consulta normal, join normal.
create table orders (...);
-- eventos, gravados na mesma transação
create table event (
id bigserial primary key,
stream_type text not null,
stream_id uuid not null,
version int not null,
type text not null,
payload jsonb not null,
occurred_at timestamptz not null,
unique (stream_type, stream_id, version)
);
Você fica com histórico completo, capacidade de auditoria, base pra integração via outbox e a possibilidade de migrar pra event sourcing de verdade depois, porque os eventos já existem.
E mantém consulta simples, consistência forte e um modelo que qualquer pessoa entende no primeiro dia.
É noventa por cento do benefício por dez por cento do custo. Em quase todo produto, essa é a conta certa.
O sinal de que você precisa mesmo
Se o seu time está perguntando “será que a gente devia usar event sourcing?”, a resposta provavelmente é não. Quando é sim, isso costuma aparecer como uma necessidade concreta e recorrente: alguém pedindo reprocessamento do passado toda semana, ou uma exigência regulatória explícita.
Padrão adotado por necessidade tem chance. Padrão adotado por elegância cobra depois, e cobra do time inteiro.