O que é deduplicação e por que ela é necessária
Processar o mesmo evento duas vezes pode ser catastrófico
Deduplicação é o processo de identificar e descartar cópias de uma mesma operação antes que sejam processadas novamente. Em sistemas distribuídos, mensagens chegam duplicadas com frequência: por retransmissões TCP, reenvios de clientes após timeout, reentregas de filas com garantia "ao menos uma vez" ou falhas parciais que deixam o sistema em estado incerto. Sem deduplicação, cobranças duplicam, emails são enviados duas vezes, pedidos são criados em dobro - efeitos diretos que o usuário percebe e que custam dinheiro, suporte e reputação para corrigir.
A diferença entre deduplicação e idempotência
Idempotência é sobre o resultado; deduplicação é sobre o rastreamento
Idempotência garante que executar uma operação múltiplas vezes produz o mesmo resultado que executar uma vez. Deduplicação é o mecanismo que detecta ativamente quando uma operação já foi processada e a descarta. Idempotência é uma propriedade do design; deduplicação é uma implementação de rastreamento. Na prática, funcionam juntas: a operação é desenhada para ser idempotente (resultado consistente), e a deduplicação garante que só execute uma vez (prevenção ativa). Em filas de mensagens, por exemplo, o worker precisa dos dois: idempotência no processamento e deduplicação para evitar reprocessamento.
Fontes de duplicação em produção
Onde duplicatas surgem e por que são inevitáveis
As principais fontes de duplicação em sistemas reais são: clientes com retry automático após timeout sem saber se a requisição chegou ao servidor, filas de mensagens com garantia "ao menos uma vez" (SQS, RabbitMQ padrão) que reentregam quando o consumer não confirma a tempo, reprocessamentos após falhas de infraestrutura como reinícios de pod ou crash do worker no meio de uma operação, e webhooks que reenviam quando o receptor retorna erro ou demora para responder. Duplicação não é um bug de implementação - é um comportamento esperado de redes e sistemas distribuídos. O bug é não estar preparado para ela.
Chaves de deduplicação - identificando o que já foi processado
Um identificador único que representa a intenção, não a tentativa
A estratégia central é criar ou exigir um identificador único para cada operação de negócio - chamado de deduplication key, message ID ou idempotency key. Esse identificador deve ser gerado pelo originador (não pelo processador), persistido antes de qualquer side effect, e verificado no início de cada processamento. Para filas como SQS FIFO, o MessageDeduplicationId faz isso automaticamente dentro de uma janela de 5 minutos. Para outras filas, o worker precisa implementar: armazenar o ID do evento em banco ou cache, verificar antes de processar, e só então executar a operação de negócio.
Armazenamento do estado de processamento
Redis, banco de dados ou tabela dedicada - cada um com seus trade-offs
Para rastrear quais eventos já foram processados, as opções mais comuns são: Redis com TTL (eficiente para grandes volumes, mas perde dados se reiniciar sem persistência), tabela dedicada no banco relacional com index no deduplication_key (durável, transacional, mais lento), DynamoDB com TTL e ConditionalExpression (para sistemas AWS), e coluna no próprio registro do domínio (quando o evento mapeia diretamente para um registro único no sistema, como um orderId). A escolha depende do volume, da latência aceitável e de quanto tempo é necessário guardar o estado - geralmente 24h a 7 dias é suficiente.
Race conditions na deduplicação
Dois workers processando o mesmo evento ao mesmo tempo
O cenário mais perigoso é dois workers consumindo o mesmo evento simultaneamente antes que qualquer um salve o registro de processamento. A solução é garantir atomicidade na verificação e no registro: usar INSERT ... ON CONFLICT DO NOTHING (PostgreSQL), SET NX no Redis (set if not exists), ou uma transação que verifica e insere de forma atômica. Sem isso, a janela de tempo entre "verificar se existe" e "inserir registro" permite que dois workers passem ao mesmo tempo pela verificação - e ambos processem o evento. Em filas com consumidores paralelos, essa race condition é mais comum do que parece.
Deduplicação em webhooks externos
Gateways de pagamento, serviços de email e notificações podem reenviar
Sistemas externos como gateways de pagamento (Stripe, Mercado Pago), serviços de email (SendGrid, Postmark) e plataformas de mensagens (WhatsApp Business API) enviam webhooks com reenvio automático quando o receptor não responde com 200 dentro de alguns segundos. Para deduplicar, use o ID do evento fornecido pelo serviço externo (exemplo: evt_123 do Stripe) como deduplication key. Retorne 200 imediatamente ao receber o webhook, coloque o processamento em fila assíncrona, e deduplique no worker usando esse ID. Dessa forma, o gateway considera entregue e o sistema processa exatamente uma vez.
Janela de deduplicação e TTL adequado
Quanto tempo manter o registro de eventos processados
Guardar o registro de processamento para sempre é impraticável - cresce indefinidamente e gera custo de armazenamento. A janela de deduplicação deve cobrir o tempo máximo em que uma duplicata pode chegar: para retries de cliente, 24h é o padrão comum (Stripe usa exatamente isso). Para reentregas de fila, o TTL do registro deve ser maior que a janela de visibilidade máxima da fila. Para webhooks, considerar o tempo máximo de retry do serviço externo (Stripe tenta por 72h). Deduplication keys expiradas permitem que operações com o mesmo ID sejam processadas novamente após o período - o que geralmente é o comportamento correto.
Testando deduplicação antes de ir para produção
Como simular duplicatas para garantir que o sistema está protegido
Testar deduplicação exige provocar as situações reais: enviar a mesma mensagem duas vezes para a fila e verificar que só um efeito aconteceu, reenviar a mesma requisição HTTP com a mesma chave e confirmar que o segundo retorno é idêntico ao primeiro sem processar novamente, e simular crash do worker após processar mas antes de confirmar para verificar que o reprocessamento na reentrega é seguro. Testes unitários validam a lógica de verificação; testes de integração validam o comportamento real com concorrência e reentregas. Deduplicação sem teste é só esperança de que vai funcionar.
Conclusão - deduplicação como proteção estrutural
Não é opcional para sistemas que precisam de confiabilidade real
Deduplicação não é uma otimização para ser adicionada depois - é uma proteção estrutural obrigatória em qualquer sistema que lida com dinheiro, comunicações ou dados críticos. Os padrões são estabelecidos, as ferramentas estão disponíveis e o custo de implementar é baixo comparado ao custo de corrigir duplicatas em produção. Comece pela fonte mais provável no seu sistema - webhook externo, fila de mensagens ou retry de cliente - e proteja de dentro para fora. Continue em: Fundamentos obrigatórios antes de produção.
Deduplicação em Sistemas Distribuídos - Vídeos
Message deduplication - Messaging in distributed systems | DevMentors EN
Idempotency in Cows and REST APIs - entendendo deduplicação via idempotência
Idempotency Explained - REST API e deduplicação na prática
Idempotency in APIs Explained - como evitar processamento duplicado
Algorithms You Should Know For System Design - ByteByteGo
Kafka In 3 Minutes - sistema de streaming com deduplicação nativa
Reels - Sistemas e Arquitetura
@bytebytego
ByteByteGo no Facebook
Referências e Leituras Recomendadas
Como testar que sua API é resiliente e segura para produção real
Ver post completo no X →Implementando padrões de resiliência em .NET Core com exemplos reais
Ver post completo no X →Vertical Slice Architecture - organizando sistemas para escala
Ver post completo no X →5 anos com Clean Architecture - lições de sistemas em produção
Ver post completo no X →Design de APIs resilientes - retry, backoff e idempotência juntos
Ver post completo no X →Monolito vs Microsserviços - como escolher para cada contexto
Ver post completo no X →