O que e idempotência?

Uma operação idempotente pode ser repetida sem causar efeitos colaterais adicionais.

Idempotência e a propriedade de uma operação que pode ser executada múltiplas vezes com o mesmo resultado. Em matematica, uma função e idempotente se f(f(x)) == f(x). Em sistemas de software, significa que chamar o mesmo endpoint mais de uma vez não deve gerar dados duplicados, cobrar duas vezes ou criar recursos extras. Esse conceito e fundamental em APIs que precisam lidar com retries, falhas de rede e timeouts. Quando uma requisição não recebe resposta, o cliente precisa poder reenviar com segurança sem medo de consequências indesejadas.

Quais metodos HTTP são idempotentes?

GET, PUT e DELETE são idempotentes por definição. POST não e.

A específicação HTTP define quais metodos são idempotentes. GET, HEAD e OPTIONS apenas leem dados sem alterar estado, portanto são sempre idempotentes. PUT substitui um recurso inteiramente, chamar PUT duas vezes com os mesmos dados produz o mesmo resultado. DELETE remove um recurso, deletar algo que ja foi deletado retorna 404, mas o estado final e o mesmo. POST cria um novo recurso a cada chamada por definição, logo não e idempotente. PATCH depende da implementação e deve ser tratado com cuidado extra em sistemas que exigem confiabilidade.

O que e uma idempotency key?

Uma chave única enviada pelo cliente que permite ao servidor deduplicar requisições.

A idempotency key e uma string única gerada pelo cliente e enviada no header da requisição, geralmente como Idempotency-Key. O servidor armazena essa chave junto com o resultado da operação. Se a mesma chave chegar novamente, o servidor retorna o resultado anterior sem reprocessar. Esse padrão e amplamente usado em APIs de pagamento como Stripe e Adyen. A chave costuma ser um UUID v4 gerado pelo cliente antes da chamada. Ela garante que mesmo que a requisição seja reenviada por timeout ou falha de rede, a cobrança acontece apenas uma vez.

At-least-once delivery em mensageria

Sistemas de mensageria podem entregar a mesma mensagem mais de uma vez.

Em sistemas de mensageria como Kafka, RabbitMQ e SQS, a garantia at-least-once significa que uma mensagem sera entregue pelo menos uma vez, mas pode ser entregue mais. Isso acontece porque o broker precisa confirmar a entrega e, em caso de falha antes do acknowledgment, reenvia a mensagem. Para que o sistema funcione corretamente, os consumidores precisam ser idempotentes. Ou seja, processar a mesma mensagem duas vezes deve produzir o mesmo resultado que processar uma vez. Isso exige que o consumidor detecte mensagens duplicadas e as ignore graciosamente.

Exactly-once semantics

A garantia mais forte e também a mais custosa em termos de performance.

Exactly-once semantics garante que uma mensagem e processada exatamente uma vez, nem mais nem menos. O Kafka oferece essa garantia com transações entre producers e consumidores desde a versão 0.11. Para ativar, e necessário configurar o producer com enable.idempotence=true e usar transações no producer e no consumidor. O custo e latência maior e complexidade adicional. Para a maioria dos casos, at-least-once com consumidores idempotentes e suficiente e mais performatico. Exactly-once faz mais sentido em contextos financeiros ou de auditoria onde duplicatas são inaceitáveis mesmo em situações extremas.

Deduplicação no banco de dados

Salvar a chave de idempotência com UNIQUE constraint e a estrategia mais robusta.

Uma das formas mais solidas de implementar idempotência no backend e criar uma tabela de idempotency_keys com colunas para a chave, o resultado serializado e o timestamp. A chave tem constraint UNIQUE no banco. Quando uma requisição chega, o backend tenta inserir a chave. Se a inserção falhar por conflito de unicidade, o resultado armazenado e retornado. Essa abordagem funciona mesmo com múltiplas instâncias do serviço rodando em paralelo, pois o banco de dados e a fonte da verdade. O resultado deve ser serializado e armazenado junto para que a resposta seja idêntica a original.

Idempotência em pagamentos

Cobrar um cliente duas vezes por uma compra e um dos piores erros de uma API financeira.

Em APIs de pagamento, idempotência e crítica. Uma falha de rede entre o cliente e o servidor pode fazer com que o cliente não saiba se a cobrança foi realizada. Sem idempotência, o cliente reenvia e o cliente e cobrado duas vezes. Com idempotência via idempotency key, o servidor reconhece a requisição duplicada e retorna o resultado da cobrança original sem processar novamente. O Stripe, por exemplo, exige idempotency key em todas as operações de criação de charge e payment intent. A key deve ser única por tentativa de pagamento, não por sessão do usuário.

Consumidores idempotentes em event-driven systems

Todo consumidor de eventos deve tolerar receber o mesmo evento mais de uma vez.

Em arquiteturas orientadas a eventos, consumidores precisam ser projetados para tolerar duplicatas. A estrategia mais comum e manter um registro dos event IDs ja processados. Quando um evento chega, o consumidor verifica se o ID ja esta no registro. Se sim, ignora. Se não, processa e registra o ID. Esse registro pode ser um campo no banco de dados, uma entrada no Redis com TTL ou uma coluna em uma tabela de processamento. O TTL deve ser maior que o tempo máximo de redelivery do broker. Essa estrategia funciona para qualquer tipo de evento e independe da tecnologia de mensageria utilizada.

Exemplos práticos de idempotência

Casos reais onde idempotência salva o sistema de erros graves.

Exemplo 1: usuário clica duas vezes no botao de finalizar compra por engano, sem idempotência, dois pedidos são criados. Com idempotency key, apenas um. Exemplo 2: worker processa uma mensagem de envio de email mas cai antes de dar o ack, o broker reenvia e o email seria duplicado. Com deduplicação por event ID, o segundo processamento e ignorado. Exemplo 3: API de criação de usuário recebe timeout mas o usuário ja foi criado no banco, no retry sem idempotência, o backend retorna erro de email duplicado. Com idempotency key, retorna o usuário criado na primeira tentativa.

Resumo final

Sistemas confíveis tratam retries como algo normal, não como exceção.

Idempotência não e um detalhe de implementação, e uma propriedade de design que define se um sistema e confiável sob falhas. Em distribuídos, falhas de rede, timeouts e redeliveries são esperados, não excepcionais. Projetar operações idempotentes desde o inicio evita cobranças duplicadas, dados inconsistentes e estados inválidos. As ferramentas são simples: idempotency key no header, tabela de deduplicação no banco, consumidores que verificam event IDs antes de processar. O custo de implementar idempotência e baixo. O custo de não implementar pode ser a confianca do usuário no sistema.

Tutoriais em Video

Conceitos-chave

Idempotência

Operação que pode ser executada múltiplas vezes com o mesmo resultado, re-execução não causa efeitos colaterais extras

HTTP methods idempotentes

GET HEAD OPTIONS PUT DELETE são idempotentes por definição; POST não e idempotente por padrão

Idempotency key

Chave única gerada pelo cliente enviada no header, servidor usa para deduplicar requisições duplicadas

At-least-once delivery

Garantia de entrega em sistemas de mensageria, pode entregar mais de uma vez, consumidores devem ser idempotentes

Exactly-once semantics

Garantia mais forte e custosa, Kafka transactions oferecem exactly-once entre producers e consumidores

Deduplicação no banco

Salvar chave de idempotência em tabela com UNIQUE constraint, rejeitar duplicatas graciosamente

Idempotência no Instagram

@bytebytego

Reels, Idempotência

@bytebytego

Idempotência no Facebook

Idempotência no X (Twitter)

@mjovanovictech

Software architecture patterns explained

Ver post completo no X →
@mjovanovictech

System design best practices

Ver post completo no X →
@mjovanovictech

Domain events and distributed systems

Ver post completo no X →
@mjovanovictech

Building resilient distributed systems

Ver post completo no X →
@mjovanovictech

Microservices vs monolith decisions

Ver post completo no X →
@mjovanovictech

Software design fundamentals

Ver post completo no X →

O que devs dizem

Lucas F. ★★★★★

Implementei idempotency key na API de pagamentos da nossa fintech e eliminamos completamente as cobranças duplicadas. O padrão do Stripe e simples de seguir e o retorno foi imediato em redução de chargebacks.

Ana C. ★★★★★

Deduplicação via UNIQUE constraint no banco e a solução mais robusta que ja vi. Funciona com múltiplas instâncias sem precisar de lock distribuído. Simples, confiável e fácil de testar.

Marcos T. ★★★★☆

A parte mais difícil foi convencer o time de que retries são normais e que o sistema precisa ser projetado para isso desde o inicio. Depois que todo mundo entendeu idempotência, a confiabilidade do sistema subiu muito.