Tudo parece normal.
A aplicação está consumindo mensagens, os logs mostram atividade, o lag não parece fora de controle e o fluxo segue rodando em produção.
Só que, algum tempo depois, alguém percebe um problema incômodo: certos dados simplesmente não foram persistidos.
A mensagem passou pelo consumer, mas o efeito esperado nunca apareceu no banco, no sistema de destino ou no estado final da operação.
Em muitos casos, a causa não está no broker nem em uma “mensagem perdida” no transporte. O problema está no momento em que o consumer decidiu confirmar avanço de leitura.
É aqui que o auto commit pode mentir.
O que o commit realmente está confirmando
Em Kafka, cada consumer acompanha sua posição de leitura por meio do offset.
O offset é, na prática, o marcador que indica até onde aquele consumer já avançou em uma partition.
Quando o consumer faz commit, ele registra que determinada posição já pode ser considerada concluída para futuras retomadas.
Esse ponto é importante: fazer commit não significa que a lógica de negócio terminou com sucesso.
Significa apenas que o consumer confirmou para o Kafka qual é o próximo ponto a partir do qual pretende continuar lendo.
Com auto commit, essa confirmação acontece automaticamente em intervalos configurados, sem depender do sucesso real do processamento da mensagem.
Com commit manual, o consumer controla esse momento de forma explícita e pode decidir confirmar o offset só depois que o trabalho crítico foi realmente concluído.
Essa diferença parece pequena no código, mas muda bastante a confiabilidade do consumo.
O cenário que costuma enganar em produção
Imagine um consumer lendo uma mensagem de atualização de pedido.
O registro é recebido normalmente, o código entra na rotina de processamento e o offset acaba sendo commitado automaticamente.
Até aqui, olhando de fora, tudo parece saudável. O consumer leu a mensagem e o grupo avançou.
Mas logo depois acontece a parte crítica: antes de persistir o dado no banco, a aplicação falha.
Pode ser uma exceção não tratada, queda do processo, interrupção da instância ou erro em algum recurso externo.
O efeito prático é o mesmo. O offset já foi confirmado, mas a lógica de negócio não terminou.
Quando a aplicação volta, aquele registro não será lido de novo como se estivesse pendente.
Do ponto de vista do Kafka, o consumer já informou que avançou além daquela mensagem.
É por isso que o auto commit pode criar uma falsa sensação de sucesso: o progresso de leitura foi confirmado, mas o processamento real ficou incompleto.
Em muitos times, o auto commit não fica ativo apenas por conveniência. Ele também costuma ser mantido porque a estratégia de retry e tratamento de falhas já foi desenhada em volta desse comportamento. O problema é que retry, por si só, não corrige o momento errado do commit. Se o offset avançar antes da conclusão real do processamento, a aplicação pode falhar depois e ainda assim deixar para trás uma perda lógica difícil de perceber.
O impacto real desse comportamento
O primeiro impacto é a perda lógica de mensagem.
A mensagem pode até ter sido entregue ao consumer, mas o efeito esperado nunca foi materializado. Na prática, o sistema se comporta como se aquele evento tivesse desaparecido do fluxo de negócio.
O segundo impacto é a inconsistência de dados.
Quando parte do processamento foi concluída e outra parte não, surgem estados quebrados: pedido criado sem atualização de estoque, evento registrado sem persistência final, integração parcial sem reconciliação clara.
O terceiro impacto é a dificuldade de diagnóstico.
Como o offset já avançou, o time muitas vezes não enxerga backlog, não vê retry natural e não encontra erro óbvio olhando apenas para métricas superficiais de consumo.
O problema passa a parecer intermitente, raro ou até “impossível de reproduzir”, quando na verdade o sistema confirmou leitura cedo demais.
Boas práticas para reduzir esse risco
A primeira é considerar commit manual depois do sucesso real do processamento.
Se a mensagem só pode ser considerada concluída após persistência, chamada externa ou atualização de estado, o commit precisa respeitar esse ponto de verdade.
A segunda é garantir idempotência.
Em sistemas distribuídos, reprocessamento não é exceção. Se uma mensagem puder ser executada novamente sem corromper o resultado final, a recuperação de falhas fica muito mais segura.
A terceira é tratar erros explicitamente.
Falha de processamento não deve se misturar com avanço silencioso de offset. É melhor decidir conscientemente entre retry, registro de erro, envio para tratamento posterior ou interrupção controlada do fluxo do que deixar o sistema “seguir em frente” com perda lógica escondida.
Kafka entrega, mas quem garante o processamento é o consumidor
Kafka não garante que a sua lógica de negócio foi executada com sucesso.
Ele garante entrega e coordenação de leitura dentro do modelo proposto pela plataforma.
A confiabilidade do processamento depende de como o consumer confirma offsets, trata falhas e protege operações críticas.
Por isso, auto commit não deve ser encarado como simples conveniência operacional.
Em muitos cenários, ele pode mentir.
A mensagem foi lida, o offset avançou, o gráfico parece saudável e ainda assim o dado não chegou onde precisava chegar.
No fim, o Kafka não confirma processamento. Quem faz essa garantia, ou deixa de fazer, é o consumidor.
