Close Menu
Código Simples .NETCódigo Simples .NET
    Facebook X (Twitter) Instagram
    Trending
    • Como grandes empresas evitam pagamentos duplicados
    • Estratégias de Resiliência para Microservices: Aplicando Back-pressure e Bulkhead com Eficiência
    • Potencializando o MongoDB com IA: Conheça o MCP Server da MongoDB
    • Guia Completo: Integrando o MCP com Atlassian
    • Model Context Protocol (MCP): O Futuro da Interação com Modelos de IA
    • Processamento Assíncrono: Os Desafios da Escalabilidade
    • NewSQL em 2025: O Estado Atual, Tendências e o Futuro dos Bancos de Dados Relacionais Escaláveis
    • 12 Regras Essenciais para Reduzir a Latência de Aplicações
    Facebook X (Twitter) Instagram
    Código Simples .NETCódigo Simples .NET
    Código Simples .NETCódigo Simples .NET
    Home»Arquitetura»Como grandes empresas evitam pagamentos duplicados

    Como grandes empresas evitam pagamentos duplicados

    Jhonathan SoaresBy Jhonathan Soares24 de julho de 20255 Mins Read Arquitetura
    Share
    Facebook Twitter LinkedIn WhatsApp Copy Link

    Imagine que um cliente clique duas vezes no botão “Finalizar pagamento” em um aplicativo de delivery ou ecommerce. Ou que a rede falhe logo após o envio de uma requisição de checkout, mas antes da confirmação para o cliente. Como garantir que o sistema não processe a mesma compra duas vezes?

    A resposta está em um conceito fundamental para sistemas financeiros e distribuídos: idempotência.

    Neste artigo, vamos explorar como empresas como Stripe, Uber e outras implementam APIs idempotentes para garantir que operações críticas sejam executadas uma e apenas uma vez.

    O problema da duplicidade

    Requisições HTTP podem ser reexecutadas por inúmeras razões:

    • O cliente reenvia manualmente a requisição.
    • O frontend ou SDK faz retry automático.
    • O servidor retorna timeout ou erro intermitente, mas processou a operação.
    • Algum proxy intermediário reenvia o pacote.

    Em operações como criação de pedidos, cobranças, transferências bancárias ou reservas, isso pode ser catastrófico: gerar cobranças duplicadas, inventários inconsistentes ou clientes frustrados.

    Para entender melhor a motivação por trás da idempotência e como ela se relaciona com o conceito de operações seguras em sistemas distribuídos, recomendamos também o artigo: 👉 Idempotência em software: conceitos, importância e aplicações

    Idempotência na prática: 10 técnicas essenciais

    Vamos destrinchar as técnicas usadas por empresas que lidam com alto volume de operações críticas, como Stripe e Shopify:

    1. APIs idempotentes por design

    Projetar uma API idempotente não é apenas adicionar uma verificação de chave. Exige pensar no fluxo como um todo: onde há efeitos colaterais? O que acontece se a operação for repetida? Por exemplo, se sua API cria uma cobrança e envia um e-mail, você precisa garantir que o e-mail não será disparado novamente num retry. Isso exige separar ações idempotentes de não-idempotentes ou adotar mecanismos de compensação.

    2. Uso de UUIDs como idempotency key

    A escolha de UUID como chave vem do seu alto grau de entropia e unicidade. Ao contrário de hashes baseados em payload, UUIDs não dependem do conteúdo da requisição, o que os torna mais versáteis — e menos propensos a colisões por mudanças sutis de payload. Um UUID pode ser criado no frontend, no mobile ou em edge servers com total segurança.

    3. Envio da chave via HTTP Header

    Padronizar o header Idempotency-Key facilita a interceptação por middlewares, logging e até ferramentas de observabilidade. Também evita que a chave se perca em cache de requisições GET e evita exposição em logs de URL. Alguns proxies e gateways, como API Gateway da AWS ou Apigee, já reconhecem e propagam esses headers de forma nativa.

    4. Chave nova para payload novo

    Reutilizar o mesmo UUID para dois conteúdos diferentes quebra o modelo de idempotência. Isso pode gerar retornos inconsistentes, falhas de integridade ou respostas não confiáveis. Uma prática recomendada é atrelar a geração do UUID à mudança de conteúdo da operação: novo carrinho, nova cobrança, nova transação. Frontends modernos automatizam isso com hooks de formulário ou stores reativos.

    5. Armazenamento da chave em banco

    Persistir a chave com o payload de resposta (e eventualmente status da requisição) permite que o sistema reconheça repetições. Essa base deve ter características de durabilidade, baixa latência e alta consistência. Redis pode ser usado com TTLs para baixa criticidade, mas para sistemas financeiros, bancos relacionais transacionais (PostgreSQL, MySQL, etc.) são preferíveis.

    6. Consulta antes de processar

    A verificação deve ser a primeira operação executada. Não adianta executar lógica de negócio e só depois consultar a chave. Esse padrão exige disciplina na arquitetura: middlewares, filters ou interceptadores podem garantir que esse passo seja uniforme. Também pode ser necessário replicar a verificação entre múltiplas instâncias da aplicação.

    7. Processa apenas se for novo

    A atomicidade aqui é crítica: entre o tempo de checar se a chave existe e gravá-la, o sistema pode estar concorrendo com outra instância. O ideal é que a verificação e gravação ocorram em uma operação única e atômica — como um INSERT ... ON CONFLICT DO NOTHING ou SELECT FOR UPDATE com lock pessimista.

    8. Rollback em caso de erro interno

    Falhas em middlewares, validações tardias ou na persistência final podem deixar a operação pela metade. Técnicas como unit of work, transações distribuídas ou uso de outbox pattern com mensageria confiável (Kafka, SQS) ajudam a preservar a consistência. Em bancos que suportam ACID completo, rollback pode ser automático — mas cuidado com dependências externas como gateways de pagamento.

    9. Expiração da chave

    Guardar todas as chaves para sempre não é escalável. TTLs ajudam a equilibrar uso de disco e segurança contra reexecução. O tempo ideal depende do SLA de repetição: se clientes podem reexecutar em até 24h, esse deve ser o TTL. Além disso, logs, métricas e dashboards devem sinalizar usos inválidos de chave repetida.

    10. Retry com backoff exponencial e jitter

    A prática de retries precisa ser feita com cuidado. Sem jitter, múltiplos clientes disparam novas requisições ao mesmo tempo — criando picos. Com jitter, os intervalos se tornam irregulares, evitando sobrecarga. Em sistemas assíncronos, pode-se usar filas com delay progressivo, e em sistemas síncronos, bibliotecas de retry com backoff adaptativo.

    Para uma visão mais ampla sobre como lidar com sistemas sob pressão, leia: 👉 Processamento assíncrono: os desafios da escalabilidade

    Exemplo real simplificado (pseudocódigo)

    [HttpPost("/checkout")]
    public IActionResult Checkout([FromHeader(Name = "Idempotency-Key")] string idemKey, OrderRequest body)
    {
        var result = idemRepo.Find(idemKey);
        if (result != null) return Ok(result);
    
        using var tx = db.BeginTransaction();
    
        var order = OrderService.Create(body);
        PaymentGateway.Charge(order);
    
        idemRepo.Save(idemKey, order);
        tx.Commit();
    
        return Ok(order);
    }

    Esse exemplo demonstra a ordem correta das operações: validação da chave, execução protegida por transação e persistência do resultado.


    Conclusão

    Idempotência não é um recurso de luxo: é uma exigência para sistemas confiáveis em ambiente distribuído. Implementar corretamente esse padrão é garantir que cada intenção do usuário seja tratada de forma única, previsível e segura.

    E, como vimos, com boas práticas e padrões simples, você pode blindar seu sistema contra os efeitos colaterais de retries, timeouts e falhas de comunicação.

    Quer ir além da idempotência?

    Conheça outros padrões de resiliência como bulkhead e back-pressure no artigo: Estratégias de resiliência para microservices

    Share. Facebook Twitter LinkedIn Telegram WhatsApp Copy Link
    Jhonathan Soares
    • Website
    • Facebook
    • X (Twitter)
    • LinkedIn

    Criador do blog Código Simples e com mais 15 anos de experiência em TI, com títulos de MVP Microsoft na área de Visual Studio Development, Neo4j Top 50 Certificate, Scrum Master e MongoDB Evangelist.

    Posts Relacionados

    Estratégias de Resiliência para Microservices: Aplicando Back-pressure e Bulkhead com Eficiência

    Microsserviços 17 de junho de 20257 Mins Read

    Processamento Assíncrono: Os Desafios da Escalabilidade

    Arquitetura 12 de maio de 20256 Mins Read

    12 Regras Essenciais para Reduzir a Latência de Aplicações

    Arquitetura 5 de maio de 20255 Mins Read
    Newsletter

    Digite seu endereço de e-mail para receber notificações de novas publicações por e-mail.

    Junte-se a 25mil outros assinantes
    Posts recentes
    • Como grandes empresas evitam pagamentos duplicados
    • Estratégias de Resiliência para Microservices: Aplicando Back-pressure e Bulkhead com Eficiência
    • Potencializando o MongoDB com IA: Conheça o MCP Server da MongoDB
    • Guia Completo: Integrando o MCP com Atlassian
    • Model Context Protocol (MCP): O Futuro da Interação com Modelos de IA
    Categorias
    • Arquitetura (17)
      • Microsserviços (1)
      • Testes (2)
    • Asp.net (120)
      • C# (89)
      • Mvc (13)
    • Banco de dados (91)
      • NoSql (59)
      • Sql (38)
    • Boas práticas (30)
      • Gestão & Produtividade (2)
      • Metodologias Ágeis (6)
    • Cursos (52)
    • Dicas (105)
    • Front-End (92)
    • IA (4)
    • Linux (6)
    • NodeJS (4)
    • Post do Leitor (9)
    • Python (5)
    • Seo (12)
    • Tecnologia (30)
      • ITIL (1)
      • Padrões de Projeto (4)
    • Testes (2)

    VEJA TAMBÉM

    Cursos
    12 de fevereiro de 20166 Mins Read

    1000 livros gratuitos sobre programação!

    Olha que dica bacana! A pagina só com livros sobre programação é mantida no GitHub…

    30 APIs Gratuitas para desenvolvedores

    Facebook X (Twitter) Instagram LinkedIn

    Type above and press Enter to search. Press Esc to cancel.

    Vá para versão mobile