Pular para o conteúdo

apps/data-patterns/idempotency-pattern

093 · Dados & Persistência · ≈ 6 min de estudo

Idempotency Pattern

Executar a mesma requisição várias vezes tem o mesmo efeito que executá-la uma vez. O cliente manda um Idempotency-Key por intenção de operação; o servidor grava a chave, o efeito e a resposta na mesma transação, e toda retentativa com a chave recebe a resposta gravada. Use em toda rota que muta estado financeiro e pode ser reenviada.

passos
6
arquivos
6
teste
1
tecnologias
5
Infraestrutura realTypeScriptBunElysiaPostgreSQLDocker
Baixar cartão

Cenário

O app envia um PIX de R$ 150,00, a resposta se perde por timeout e o app reenvia. Sem a camada, a conta seria debitada duas vezes. Com a Idempotency-Key, a retentativa recebe a resposta da primeira execução e a conta é debitada uma vez só — inclusive quando várias cópias chegam no mesmo instante.

Planta

Sequência
8/8
POST /pix (Idempotency-Key K)1INSERT chave K sem resposta2BEGIN, trava conta, debita, grava PIX e resposta em K, COMMIT3201 (resposta perdida na rede)4POST /pix (mesma K, mesmo corpo)5chave K já existe6hash igual e resposta gravada7201 + X-Idempotent-Replay: true, sem novo débito8mesma K com corpo diferente: 422. K ainda sem resposta: 409AppAPI PIXPostgreSQL
8

8 passos — reproduza para seguir o fluxo

Como funciona

6 passos

Chave única impede efeito duplicado.

Esconde cada passo: lembre antes de tocar para revelar.

Vocabulário compartilhado

Idempotency-Key+3
X-Idempotent-Replay: true+1
  1. 01

    A rota exige Idempotency-Key em formato UUID, gerada pelo cliente uma vez por operação

  2. 02

    O servidor calcula o SHA-256 do corpo e tenta reservar a chave; só uma requisição consegue

  3. 03

    Quem reserva roda o PIX (trava a conta, valida saldo, debita) e grava status e corpo da resposta na mesma transação — recusa de negócio (422) também fica gravada

  4. 04

    Quem não reserva responde pela chaveHash diferente → 422, sem resposta ainda → 409, resposta gravada → replay com X-Idempotent-Replay: true

  5. 05

    Falha técnica não commita nada e libera a chave; lock de tentativa que caiu expira em 30 s

  6. 06

    A chave vale 24 horas, tempo de sobra para retentativas com backoff; linhas vencidas são apagadas

Trade-offs

O que se ganha, o que se paga

3 vantagenscada ganho tem um preço3 custos

Vantagens

  • Retentativa segura, sem débito duplo

  • Recusa e sucesso devolvidos iguais na retentativa

  • Concorrência resolvida pela chave primária

Custos

  • Uma escrita a mais por chamada

  • Tabela de chaves exige retenção e limpeza

  • Cliente precisa gerar e reenviar a mesma chave

apps/data-patterns/idempotency-pattern

6 arquivos

sql/

  • 01_schema.sqlschemaaccounts, pix_transfers e idempotency_keys

src/

  • idempotency_layer.tsReserva da chave, ramos 409/422/replay e liberação em falha técnica
  • api_pix.tsRota POST /pix com débito sob lock
  • demo.tsdemoRetentativas, mau uso da chave e recusa gravada
  • api_pix.test.tstesteReplay, 422, recusa gravada, concorrência e falha técnica contra PostgreSQL real

src/config_pix.ts / src/

  • pool_pix.tsAmbiente validado, pool e transactionExecute

Executar · com Docker

  1. ./docker.sh up# sobe PostgreSQL
  2. bun install# dependências
  3. bun run demo# roda o cenário
  4. bun run test# integração contra o serviço real
Requisitos
BunDocker
Sobe junto
PostgreSQL
Esc

↑ ↓ navegarEnter abrir191 resultados