Imagine a seguinte situação: Você acabou de realizar um pagamento pelo aplicativo do banco. Após confirmar a operação, sua conexão com a internet cai antes da resposta aparecer na tela. Sem saber se o pagamento foi realmente processado, você faz o que praticamente qualquer pessoa faria: tenta novamente.
Agora imagine que o sistema processe as duas requisições.
- Dois pagamentos.
- Duas cobranças no cartão.
- Dois pedidos registrados.
Esse é um problema muito mais comum do que parece. Em sistemas distribuídos, falhas de rede, timeouts, perda de conexão e mecanismos automáticos de Retry fazem com que uma mesma requisição possa ser enviada diversas vezes.
A pergunta é: como a API sabe que aquela operação já foi executada?
É justamente esse problema que a Idempotência procura resolver.
O que é Idempotência?
Idempotência é a propriedade que permite executar uma mesma operação diversas vezes sem alterar o resultado obtido após a primeira execução.
Em outras palavras, mesmo que uma requisição seja reenviada várias vezes, o servidor deverá produzir exatamente o mesmo efeito da primeira execução.
Isso não significa que a API ignore a nova requisição. Ela apenas identifica que aquela operação já foi processada anteriormente e devolve o mesmo resultado ao cliente, evitando efeitos colaterais como registros duplicados.
Por que esse problema acontece?
Muitas pessoas imaginam que uma requisição HTTP é enviada apenas uma vez. Na prática, isso raramente acontece em ambientes de produção.
Diversos fatores podem fazer uma mesma operação ser reenviada automaticamente.
- Timeout da requisição.
- Queda temporária da conexão.
- Retry automático do cliente.
- Retry realizado pelo API Gateway.
- Falhas temporárias na rede.
- Balanceadores de carga.
Em todos esses cenários, o cliente normalmente não sabe se a primeira requisição foi concluída com sucesso. Como consequência, ele simplesmente envia a mesma requisição novamente.
O problema das requisições duplicadas
Vamos imaginar uma API responsável por criar pagamentos.
POST /payments
Host: api.example.com
Content-Type: application/json
{
"customerId": 100,
"amount": 350.00
}A API recebe a requisição, processa o pagamento e prepara a resposta. Entretanto, exatamente nesse momento ocorre uma falha de rede. O pagamento foi criado, mas o cliente nunca recebeu a confirmação. Sem saber disso, ele envia novamente exatamente a mesma requisição. Se a API não possuir nenhum mecanismo de proteção, ela criará um segundo pagamento.
Fluxo sem Idempotência

Esse tipo de situação não acontece apenas em APIs de pagamento.
- Pedidos duplicados em e-commerce.
- Usuários cadastrados duas vezes.
- Envio duplicado de e-mails.
- Emissão repetida de notas fiscais.
- Criação duplicada de ordens de produção.
Perceba que o problema não está na rede nem no usuário. O verdadeiro desafio é permitir que uma operação seja repetida com segurança, mesmo quando ocorrerem falhas durante a comunicação.
Mas como uma API consegue identificar que uma requisição já foi executada anteriormente?
É exatamente aqui que entra um dos mecanismos mais utilizados atualmente: a Idempotency-Key.
Como a API sabe que aquela requisição já foi processada?
A solução mais utilizada atualmente é a Idempotency-Key.
Ela funciona como um identificador único enviado pelo cliente juntamente com a requisição. Sempre que uma operação precisar ser executada apenas uma vez, o cliente gera uma chave exclusiva e a envia no cabeçalho HTTP.
Se essa mesma requisição precisar ser reenviada devido a um timeout ou falha de comunicação, a mesma chave também será enviada.
Assim, a API consegue identificar que aquela operação já foi executada anteriormente.
O que é uma Idempotency-Key?
Idempotency-Key é um identificador único utilizado para representar uma operação específica. Normalmente essa chave é um UUID gerado pelo cliente antes do envio da requisição.
O servidor utiliza essa chave para verificar se aquela operação já foi processada anteriormente. Caso a resposta já exista, ela é retornada novamente sem executar a operação outra vez.
POST /payments
Host: api.exemplo.com
Idempotency-Key: 9f7d31d9-6909-49fa-94c3-38d6e7df32d8
Content-Type: application/json
{
"customerId": 100,
"amount": 350.00
}Após receber essa requisição, a API consulta sua base de dados para verificar se essa chave já foi utilizada.
Fluxo com Idempotência

Observe que, na segunda tentativa, a API não executa novamente a lógica de negócio. Ela apenas devolve a resposta registrada durante a primeira execução.
Exemplo Prático
Vamos imaginar novamente o cenário do pagamento.
Primeira tentativa:
POST /payments
Idempotency-Key: 8f73e0f1
Content-Type: application/json
{
"customerId": 100,
"amount": 350.00
}A API cria o pagamento.
Status: HTTP/1.1 201 Created
Content-Type: application/json
{
"paymentId": 451,
"status": "APPROVED"
}Agora imagine que o cliente não recebeu essa resposta por causa de um timeout.
Ele envia exatamente a mesma requisição novamente.
POST /payments
Idempotency-Key: 8f73e0f1
Content-Type: application/json
{
"customerId": 100,
"amount": 350.00
}Dessa vez, a API identifica que a chave já existe.
Em vez de criar um novo pagamento, ela retorna exatamente a mesma resposta da primeira execução.
Status: HTTP/1.1 201 Created
Content-Type: application/json
{
"paymentId": 451,
"status": "APPROVED"
}Perceba que o cliente recebe a confirmação normalmente, mas nenhum novo registro é criado no banco de dados.
Todos os métodos HTTP são idempotentes?
Não.
Alguns métodos já são considerados naturalmente idempotentes pela própria especificação HTTP. Outros dependem da forma como a aplicação foi implementada.
| Método HTTP | Idempotente? | Descrição |
|---|---|---|
| GET | ✔ Sim | Apenas consulta dados. |
| HEAD | ✔ Sim | Retorna apenas os cabeçalhos. |
| OPTIONS | ✔ Sim | Consulta recursos disponíveis. |
| PUT | ✔ Sim | Substitui completamente um recurso. |
| DELETE | ✔ Sim | Excluir novamente não altera o resultado final. |
| PATCH | ⚠ Depende | Depende da implementação. |
| POST | ❌ Não | Normalmente cria novos recursos. |
É justamente por isso que APIs de pagamento, bancos, marketplaces e plataformas de assinatura normalmente implementam Idempotency-Key para operações realizadas através do método POST.
Idempotência em Microsserviços
Até aqui utilizamos uma API REST como exemplo, mas a idempotência vai muito além disso.
Em arquiteturas baseadas em Microsserviços, uma única ação do usuário pode gerar diversos eventos e acionar vários serviços independentes.
Imagine que um cliente finalize uma compra.

Cada serviço consome o mesmo evento de forma independente.
Mas existe um detalhe importante.
Nem sempre uma mensagem é entregue apenas uma vez.
Dependendo da tecnologia utilizada, um consumidor pode receber exatamente o mesmo evento duas ou mais vezes.
Se o serviço não for idempotente, diversos problemas podem acontecer.
- O estoque pode ser reduzido duas vezes.
- O cliente pode receber dois e-mails.
- Duas notas fiscais podem ser emitidas.
- O pagamento pode ser processado novamente.
Por esse motivo, consumidores de eventos também precisam ser idempotentes.
Idempotência em Mensageria
Em sistemas que utilizam mensageria, o objetivo principal não é impedir que uma mensagem seja entregue novamente.
O objetivo é garantir que ela possa ser processada várias vezes sem alterar o resultado final.
Esse conceito é extremamente importante em plataformas como Apache Kafka e RabbitMQ.
Apache Kafka
No Kafka, um consumidor pode reprocessar mensagens após falhas, reinicializações ou mudanças de partições.
Isso significa que um mesmo evento pode chegar novamente ao consumidor.
Se a aplicação não for idempotente, o mesmo processamento poderá acontecer diversas vezes.
RabbitMQ
No RabbitMQ acontece algo semelhante.
Se um consumidor falhar antes de enviar o ACK da mensagem, ela poderá voltar para a fila e ser entregue novamente.
Por isso, o consumidor deve conseguir identificar que aquela mensagem já foi processada anteriormente.
Como implementar Idempotência
Não existe uma única forma de implementar esse mecanismo.
Entretanto, a estratégia mais comum consiste em armazenar um identificador único juntamente com o resultado da operação.
IdempotencyRequests
-----------------------------------------
Id
IdempotencyKey
StatusCode
Response
CreatedAt
ExpiresAt
-----------------------------------------
Quando uma nova requisição chega, a API consulta essa tabela antes de executar qualquer regra de negócio.
Se a chave existir, a resposta armazenada é devolvida imediatamente.
Caso contrário, a operação é executada normalmente e o resultado é salvo para futuras tentativas.
Boas Práticas
- Utilize UUID como Idempotency-Key.
- Defina um tempo de expiração para as chaves.
- Armazene também a resposta retornada ao cliente.
- Garanta que a gravação da chave e da operação seja atômica.
- Implemente logs para facilitar auditorias.
- Não reutilize uma mesma chave para operações diferentes.
Erros Comuns
- Confiar apenas no método HTTP.
- Executar a operação antes de verificar a Idempotency-Key.
- Armazenar as chaves indefinidamente.
- Ignorar processamento duplicado em consumidores de eventos.
- Não validar se a mesma chave está sendo utilizada com dados diferentes.
Conclusão
Falhas de comunicação fazem parte da realidade de qualquer sistema distribuído. Timeouts, perda de conexão e mecanismos automáticos de retry acontecem diariamente e não podem ser totalmente evitados.
Por esse motivo, APIs modernas precisam ser capazes de reconhecer quando uma mesma operação já foi executada anteriormente.
A Idempotência resolve exatamente esse problema, permitindo que uma mesma requisição seja enviada diversas vezes sem produzir efeitos colaterais adicionais.
Mais do que uma característica de APIs REST, ela é um dos pilares para construir aplicações resilientes baseadas em microsserviços, mensageria e arquiteturas orientadas a eventos.
