Ferramentas para desenvolvedores · Gerador UUID
Chaves de idempotência: usando um UUID gerado pelo cliente para tornar as novas tentativas seguras
· Por que é importante
uuid criptografia APIs do navegador
O tempo limite em uma solicitação de pagamento deixa você sem saber se ela foi processada. As chaves de idempotência permitem que você tente novamente com segurança, e uma UUID gerada por CSPRNG é a chave natural. Esta postagem explica o padrão de ponta a ponta.
O tempo limite que pode ter cobrado duas vezes do cliente — as chaves de idempotência do modo de falha existem para corrigir
Um tempo limite durante uma solicitação de pagamento cria uma incerteza genuína para o cliente e para o sistema. Seu cliente HTTP desistiu de esperar por uma resposta, mas o servidor de pagamento pode ter processado a transação antes que a conexão fosse encerrada ou expirasse. Se você tentar novamente a mesma solicitação, poderá cobrar duas vezes do cliente. Se você não tentar novamente, o pagamento nunca será concluído. O sistema de pagamento falha em um meio-termo infeliz: o dinheiro do cliente pode ter desaparecido, pode chegar amanhã, pode ficar preso em uma fila de processamento ou pode nem ter saído da conta. Esta ambiguidade é inaceitável para os sistemas financeiros.
Como funcionam as chaves de idempotência — o servidor armazena a primeira resposta na chave e a reproduz para repetições
As chaves de idempotência resolvem esse problema de maneira elegante, tornando as tentativas seguras e determinísticas. O cliente gera uma chave exclusiva para cada intenção – um pagamento, uma transferência, uma cobrança – e a inclui em cada solicitação. O servidor processa o pagamento, armazena em cache a resposta nessa chave e armazena a chave e o resultado. Se a mesma chave chegar novamente dentro de uma janela de retenção, o servidor reproduzirá a resposta armazenada em cache sem processar o pagamento novamente. O cliente pode tentar novamente com segurança, sabendo que exatamente a mesma chave sempre produzirá o mesmo resultado, não importa quantas vezes ela seja enviada. Esse padrão elimina a ambigüidade e torna a lógica de nova tentativa segura.
Gerar antes da primeira tentativa — por que a chave deve existir antes que a solicitação saia e ser reutilizada literalmente na nova tentativa
O padrão é mais antigo que as especificações HTTP modernas, mas ganhou destaque em pagamentos após perdas financeiras generalizadas e reclamações de clientes devido a cobranças duplicadas. Cada pagamento API e muitas APIs de serviços da Web agora oferecem suporte a chaves de idempotência. Um UUID gerado por CSPRNG é a escolha natural para a chave porque é indecifrável, único, sem qualquer coordenação entre clientes e não requer alocação no lado do servidor ou autoridade central. O cliente o gera antes da primeira tentativa, reutiliza-o literalmente em cada nova tentativa e recebe sempre a mesma resposta. Nenhum estado do lado do servidor é necessário para coordenar a geração de chaves.
Por que um UUID aleatório e não um contador ou hash de carga útil — exclusividade sem coordenação e sem reutilização acidental entre intenções
A chave deve existir antes que a solicitação saia do cliente porque gerá-la na nova tentativa é tarde demais para garantir a idempotência. Se a primeira solicitação fosse bem-sucedida e cobrasse do cliente, a geração de uma nova chave na nova tentativa mascararia o problema e cobraria novamente. O cliente deve confirmar uma chave antes da primeira tentativa, armazená-la na memória ou no armazenamento persistente e reutilizar essa mesma chave se um tempo limite ou nova tentativa for necessário. Para testes manuais de API, o gerador ToolAcre produz chaves que você pode colar em curl ou em um cliente REST, copiar e reutilizar em várias solicitações para testar o comportamento de idempotência.
Escopo e tempo de vida — chaves por operação, por conta e por quanto tempo o servidor deve lembrá-las
Por que um UUID em vez de um hash ou contador sequencial para chaves de idempotência? Um hash da carga útil da solicitação parece intuitivo: cargas idênticas obtêm hashes idênticos e, portanto, chaves idênticas. Mas os hashes são fracos para este caso de uso porque duas solicitações quase idênticas com quantidades diferentes, destinatários diferentes ou parâmetros diferentes produzem hashes completamente diferentes e, portanto, geram cobranças separadas, o que é correto, mas não fornece toda a proteção necessária. Um contador sequencial requer coordenação e estado distribuído: se dois clientes gerarem chaves baseadas em contadores em sua infraestrutura, seus contadores poderão colidir. Um UUID não requer autoridade central, é indecifrável e é extremamente improvável que colida por acaso em toda a Internet o tempo todo.
Exemplo resolvido - uma sequência de novas tentativas com a mesma chave, mostrando o que o cliente envia e o que o servidor retorna a cada vez
A implementação do lado do servidor armazena respostas em chaves e retorna respostas armazenadas em cache nas repetições. A complexidade está em decidir questões operacionais práticas: o período de retenção, quanto tempo para lembrar uma chave, o tamanho do cache, quantas chaves lembrar, o bloqueio, como evitar que duas solicitações simultâneas com a mesma chave processem o pagamento duas vezes e a limpeza quando esquecer uma chave. Estas são questões de armazenamento e confiabilidade fora do escopo do gerador UUID. O trabalho do cliente é gerar uma boa chave e reutilizá-la nas novas tentativas; a tarefa do servidor é implementar o cache de maneira correta e durável.
O que isso não cobre — o armazenamento e o bloqueio do lado do servidor necessários para implementar o padrão, que é um design separado
Um exemplo prático mostra uma sequência típica na prática. Um aplicativo móvel precisa transferir dinheiro para um amigo usando um API que suporte idempotência. Antes de enviar a solicitação, o aplicativo gera um UUID usando sua biblioteca de criptografia local ou busca um no gerador ToolAcre para fins de teste: 3fa85f64-5717-4562-b3fc-2c963f66afa6. O aplicativo envia uma solicitação POST para /transfers com um corpo JSON e um cabeçalho HTTP Idempotency-Key: 3fa85f64-5717-4562-b3fc-2c963f66afa6. O servidor processa a transferência, armazena 3fa85f64-5717-4562-b3fc-2c963f66afa6 → {status: "success", transferId: "xfer-12345"} em seu cache e retorna uma resposta 200 com o resultado.
Conclusão: uma intenção, uma chave — o gerador ToolAcre fornece um UUID apoiado por CSPRNG para usar como chave ao testar uma integração manualmente
A rede atinge o tempo limite e o cliente não vê a resposta na primeira tentativa. O aplicativo tenta novamente a mesma solicitação com a mesma chave de idempotência sem gerar um novo UUID. O servidor reconhece a chave em seu cache, encontra a resposta armazenada em cache e retorna imediatamente {status: "success", transferId: "xfer-12345"} sem processar uma nova transferência e sem cobrar novamente do cliente. A operação é idempotente: tentar novamente produz sempre o mesmo resultado observável. Para um teste executado, o gerador ToolAcre pode fornecer a chave; gere um UUID, inclua-o no cabeçalho, observe a resposta e reenvie com a mesma chave para verificar se o servidor implementa o cache corretamente.