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

Deduplicação e Sistemas Distribuídos no Instagram

Deduplication Key

Identificador único gerado pelo originador para identificar uma operação de negócio, independente da tentativa de envio.

Entrega ao menos uma vez

Garantia de filas como SQS e RabbitMQ padrão — pode entregar duplicatas, exige deduplicação no consumer.

SET NX (Redis)

Operação atômica set-if-not-exists no Redis — base para implementar deduplicação sem race condition.

TTL de deduplication key

Tempo de expiração do registro de processamento — normalmente 24h a 7 dias dependendo do contexto.

INSERT ON CONFLICT

Instrução SQL (PostgreSQL) que insere apenas se não existir conflito — garante atomicidade na verificação.

Webhook deduplication

Usar o ID do evento externo (ex: evt_stripe) como chave para evitar processar o mesmo pagamento duas vezes.

Deduplicação e Sistemas Distribuídos no X

@bytebytego

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

O que dizem