Pular para o conteúdo

Arquitetura real · Sênior

Stripe: APIs previsíveis com chaves de idempotência

Arquitetura real em produção. Pontos centrais: Operações Idempotentes, Fundamentos de Design de API e Padrões de Design para Nuvem.

17 min de leitura · Fonte: Stripe · Conteúdo revisado em 22 de outubro de 2026

Resposta curta

Arquitetura real em produção. Pontos centrais: Operações Idempotentes, Fundamentos de Design de API e Padrões de Design para Nuvem. Toda chamada entre dois nós atravessa uma rede, e redes falham de formas exóticas, mesmo as que são estatisticamente confiáveis. Entre um cliente e um servidor há três falhas distintas: a conexão inicial pode nem se estabelecer; a chamada pode cair…

01 · CONTEXTO

A resposta que não chega

Toda chamada entre dois nós atravessa uma rede, e redes falham de formas exóticas, mesmo as que são estatisticamente confiáveis. Entre um cliente e um servidor há três falhas distintas: a conexão inicial pode nem se estabelecer; a chamada pode cair no meio, enquanto o servidor cumpre a operação, deixando o trabalho em limbo; ou a chamada pode dar certo e a conexão cair antes de o servidor avisar o cliente.

Só a primeira falha é inofensiva: o cliente sabe que nada aconteceu e pode repetir. Nas outras duas o sucesso da operação é ambíguo do ponto de vista do cliente, que não sabe se repetir é seguro. Isso vale para qualquer sistema distribuído, e o artigo lembra que até a API do Stripe com um único outro servidor chamando-a já é um.

  1. O cliente envia o pedido de cobrança ao servidor da API.

    Diagrama da arquitetura: Cobrança sem resposta: o cliente não sabe o que houve
    CLClienteenvia o pedido
    CPServidor da API
    DBBanco de cobranças
  2. O servidor executa a operação e grava o efeito no banco: a cobrança de fato aconteceu.

    Diagrama da arquitetura: Cobrança sem resposta: o cliente não sabe o que houve
    CLCliente
    CPServidor da API
    DBBanco de cobrançasefeito gravado
  3. A conexão cai antes de a resposta chegar. Do ponto de vista do cliente, nada indica se a cobrança foi feita.

    Diagrama da arquitetura: Cobrança sem resposta: o cliente não sabe o que houve
    CLClientesem resposta
    CPServidor da API
    DBBanco de cobranças
  4. Se o cliente repetir sem nenhuma proteção, o servidor executa de novo e a cobrança acontece em dobro.

    Diagrama da arquitetura: Cobrança sem resposta: o cliente não sabe o que houve
    CLCliente
    CPServidor da API
    DBBanco de cobrançasefeito duplicado

A saída mais simples é projetar o servidor para que repetir seja sempre seguro. Um endpoint com essa propriedade se diz idempotente: pode ser chamado qualquer número de vezes com os efeitos colaterais ocorrendo uma só vez. Diante de qualquer erro, o cliente repete até ter sucesso verificável, e o estado dele converge com o do servidor.

02 · IDEMPOTENTE POR NATUREZA

Quando repetir já é seguro

O artigo usa como exemplo a API de um provedor de DNS hipotético que cria um subdomínio com um PUT. Toda a informação necessária para criar o registro vai na chamada, então o cliente pode invocá-la quantas vezes quiser; se o servidor percebe que é duplicata porque o domínio já existe, ignora o pedido e responde com sucesso. Pela semântica HTTP, PUT e DELETE são idempotentes, e o PUT cria ou substitui o recurso inteiro pelo conteúdo do corpo.

A documentação do Stripe aplica o mesmo raciocínio. Na API v1, GET e DELETE são idempotentes por definição: repeti-los não repete os efeitos da operação original, e mandar chave de idempotência neles não muda nada. Já as requisições POST, que mudam estado, aceitam a chave.

Tipo de operaçãoExemploChave de idempotência?
PUT com o estado completoCriar um registro DNS com todos os camposDispensável, repetir já é seguro
GET e DELETELer ou apagar um recursoSem efeito, são idempotentes por definição
POST que muda estadoCobrar um clienteNecessária, repetir cobraria de novo

03 · A CHAVE DE IDEMPOTÊNCIA

Exatamente uma vez, mesmo com repetição

E quando a operação precisa ocorrer uma única vez? O exemplo do artigo é um endpoint de cobrança: chamá-lo duas vezes por acidente cobraria o cliente em dobro. A chave de idempotência resolve isso. Ao fazer o pedido, o cliente gera um ID único que identifica só aquela operação e o envia junto do corpo normal; o servidor correlaciona o ID com o estado da requisição do seu lado. Se o cliente notar uma falha, repete com o mesmo ID, e cabe ao servidor decidir o que fazer.

FalhaO que o servidor faz na repetição
Falha ao conectarVê o ID pela primeira vez e processa normalmente
Falha no meio da operaçãoSe um banco ACID desfez tudo, repete por inteiro; senão recupera o estado e continua
Falha na respostaResponde com o resultado em cache da operação que deu certo

Repare que o artigo não prescreve um único comportamento: o que acontece no caso do meio depende da implementação, e é por isso que a escolha de guardar o estado de cada requisição importa tanto.

  1. O cliente gera uma chave única para a operação e a envia junto do corpo normal do pedido.

    Diagrama da arquitetura: Camada de idempotência na frente da operação
    CLClientegera a chave
    CPAPI com camada de idempotência
    DBRegistro de chaves
    CPExecução da operação
  2. A camada de idempotência consulta o registro. A chave nunca foi vista, então o pedido segue para execução.

    Diagrama da arquitetura: Camada de idempotência na frente da operação
    CLCliente
    CPAPI com camada de idempotência
    DBRegistro de chaveschave nova
    CPExecução da operação
  3. A operação roda e o servidor guarda no registro o status e o corpo da resposta, depois que a execução do endpoint começa (regra da API v1).

    Diagrama da arquitetura: Camada de idempotência na frente da operação
    CLCliente
    CPAPI com camada de idempotência
    DBRegistro de chavesresposta salva
    CPExecução da operaçãoexecuta uma vez
  4. A resposta se perde no caminho e o cliente fica sem saber o resultado.

    Diagrama da arquitetura: Camada de idempotência na frente da operação
    CLClientesem resposta
    CPAPI com camada de idempotência
    DBRegistro de chaves
    CPExecução da operação
  5. O cliente repete com a mesma chave. A camada encontra a resposta salva e a devolve, sem chamar a operação de novo.

    Diagrama da arquitetura: Camada de idempotência na frente da operação
    CLCliente
    CPAPI com camada de idempotência
    DBRegistro de chaveschave conhecida
    CPExecução da operação
  6. Se a repetição chegasse com parâmetros diferentes dos originais, a camada recusaria com erro em vez de executar.

    Diagrama da arquitetura: Camada de idempotência na frente da operação
    CLCliente
    CPAPI com camada de idempotênciarecusa
    DBRegistro de chaves
    CPExecução da operação

Quem gera a chave é o cliente. Como gerá-la fica por conta dele, mas a documentação sugere UUIDs v4 ou outra string aleatória com entropia suficiente para evitar colisões. As chaves têm até 255 caracteres e não devem carregar dados sensíveis, como e-mails ou identificadores pessoais. Uma segunda estratégia é derivar a chave de um objeto ligado ao usuário, como o ID de um carrinho de compras, o que protege de forma direta contra envio duplo.

04 · O QUE O SERVIDOR DECIDE

Executar, devolver ou recusar

Para cada repetição o servidor precisa escolher entre devolver o que já tem, recusar ou executar de verdade. A documentação do Stripe define os casos da API v1, que o quadro abaixo reúne.

Situação da repetiçãoO que acontece
Mesma chave e mesmos parâmetros, depois de a execução começarDevolve o status e o corpo salvos da primeira requisição
Mesma chave com parâmetros diferentesErro, para evitar uso indevido da chave
Parâmetros inválidos ou conflito com outra requisição em execuçãoNada é salvo, e a requisição pode ser repetida
Conflito com outra requisição, possivelmente pela mesma chaveResposta com status 409, conflito
Chave já removida e reutilizadaPode executar uma nova requisição

O cliente consegue distinguir uma resposta repetida pelo servidor procurando o cabeçalho Idempotent-Replayed com valor verdadeiro.

05 · CICLO DE VIDA DA CHAVE

Janela de repetição e reconciliação

A chave não vive para sempre. O Stripe retém as chaves por pelo menos 24 horas e pode removê-las depois disso, e reutilizar uma chave removida pode executar uma nova requisição. Por isso a orientação é limitar as repetições de uma operação não resolvida às primeiras 24 horas depois da requisição original, sempre com a mesma chave e os mesmos parâmetros.

Se o resultado continua desconhecido depois dessa janela, não se repete nem com a chave antiga nem com uma nova. Em vez disso, busca-se o objeto relevante, inspeciona-se a requisição no painel e usam-se eventos de webhook para reconciliar o resultado.

Outra regra prática: se as repetições atravessam chamadas separadas do SDK ou reinícios de processo, a aplicação deve gerar e persistir a chave da operação e fornecê-la a cada tentativa.

  1. Antes da primeira tentativa, a aplicação gera a chave da operação e a persiste.

    Diagrama da arquitetura: Ciclo de vida da chave e reconciliação
    CPAplicação do integrador
    DBChaves persistidaschave gravada
    CPAPI de pagamentos
    CPHandler de webhooks
    DBRegistros locais
  2. O pedido fica sem resposta. Enquanto a janela permite, a aplicação repete com a mesma chave e os mesmos parâmetros.

    Diagrama da arquitetura: Ciclo de vida da chave e reconciliação
    CPAplicação do integradorsem resposta
    DBChaves persistidas
    CPAPI de pagamentos
    CPHandler de webhooks
    DBRegistros locais
  3. Se o processo reinicia no meio, a aplicação lê a chave persistida em vez de criar outra.

    Diagrama da arquitetura: Ciclo de vida da chave e reconciliação
    CPAplicação do integrador
    DBChaves persistidasreaproveita
    CPAPI de pagamentos
    CPHandler de webhooks
    DBRegistros locais
  4. Passada a janela sem resultado conhecido, a aplicação para de repetir, nem com a chave antiga nem com uma nova.

    Diagrama da arquitetura: Ciclo de vida da chave e reconciliação
    CPAplicação do integradorpara de repetir
    DBChaves persistidas
    CPAPI de pagamentos
    CPHandler de webhooks
    DBRegistros locais
  5. A reconciliação busca o objeto e lê os eventos de webhook, casando o que aconteceu com os registros locais.

    Diagrama da arquitetura: Ciclo de vida da chave e reconciliação
    CPAplicação do integrador
    DBChaves persistidas
    CPAPI de pagamentos
    CPHandler de webhookslê eventos
    DBRegistros locaisestado reconciliado

06 · REPETIR COM EDUCAÇÃO

Recuo exponencial, jitter e as três regras

Repetir também tem custo. Se o servidor está num incidente com indisponibilidade real, as repetições não passam e podem agravar a degradação. Por isso se recomenda um recuo exponencial: o cliente espera pouco após a primeira falha e, conforme a operação continua falhando, espera um tempo proporcional a 2^n, em que n é o número de falhas. Mesmo assim, se muitos clientes falharam quase ao mesmo tempo, os calendários de repetição podem se alinhar e atingir o servidor juntos, o chamado problema do thundering herd. A correção é somar um jitter aleatório à espera de cada cliente.

A biblioteca Ruby do Stripe faz isso sozinha: repete automaticamente em caso de falha, com a mesma chave de idempotência, tempos de espera crescentes e jitter.

Cabeçalho Stripe-Should-RetryO que o cliente faz
VerdadeiroRepete usando recuo exponencial, para não sobrecarregar a API
FalsoNão repete
AusenteDecide pelo código de status e outras informações da resposta

Perguntas frequentes

O que é Stripe: APIs previsíveis com chaves de idempotência?

Arquitetura real em produção. Pontos centrais: Operações Idempotentes, Fundamentos de Design de API e Padrões de Design para Nuvem.

O que o design de Stripe: APIs previsíveis com chaves de idempotência cobre?

Ele está organizado nestas seções: A resposta que não chega, Quando repetir já é seguro, Exatamente uma vez, mesmo com repetição, Executar, devolver ou recusar, Janela de repetição e reconciliação e Recuo exponencial, jitter e as três regras.

Quanto tempo leva Stripe: APIs previsíveis com chaves de idempotência e qual é o nível?

Leva cerca de 17 minutos para ler e tem nível Sênior.

Agora projete você mesmo

Rode este caso como uma entrevista na escola de System Design: você toma as decisões, o tutor as questiona e você vê a nota do seu desenho.