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

Reels - Sistemas e Arquitetura

@bytebytego

ByteByteGo no Facebook

Referências e Leituras Recomendadas

@mjovanovictech

Como testar que sua API é resiliente e segura para produção real

Ver post completo no X →
@mjovanovictech

Implementando padrões de resiliência em .NET Core com exemplos reais

Ver post completo no X →
@mjovanovictech

Vertical Slice Architecture - organizando sistemas para escala

Ver post completo no X →
@mjovanovictech

5 anos com Clean Architecture - lições de sistemas em produção

Ver post completo no X →
@mjovanovictech

Design de APIs resilientes - retry, backoff e idempotência juntos

Ver post completo no X →
@mjovanovictech

Monolito vs Microsserviços - como escolher para cada contexto

Ver post completo no X →

Links Úteis