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
What is API Idempotency and Why Is It Important?
Data Modeling - Idempotency, DataExpert.io
Handle Distributed Transactions, 2PC, 3PC, SAGA Pattern
Design a Payment System, System Design Interview
RESTful APIs in 100 Seconds, Fireship
What Is A RESTful API?, Academind
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)
Links Uteis
O que devs dizem
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.
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.
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.