Projetando um Sistema de Pagamentos em Escala: Guia Completo de System Design

Resumo: Um guia de nível produção para desenhar sistemas de pagamento robustos, cobrindo autorização, captura, ledger de dupla entrada, idempotência, antifraude, conciliação, multi-moeda, subscriptions, compliance e confiabilidade operacional.

Publicado: Fevereiro 2026

Tempo de leitura: 110 minutos

Palavras-chave: #SystemDesign #PaymentSystem #Ledger #Idempotency #FraudDetection #Reconciliation #PCI #DistributedSystems #TechInterview

Pagamentos são o ponto onde software encontra dinheiro real. Quando um sistema de feed falha, o usuário vê conteúdo errado. Quando um sistema de pagamento falha, você perde dinheiro, gera disputa, cria risco regulatório e destrói confiança.

Um checkout simples parece um clique. Por trás, você precisa coordenar:

  • validação de pedido,
  • tokenização de meio de pagamento,
  • autorização,
  • captura,
  • registro contábil,
  • webhooks assíncronos,
  • conciliação com provedores,
  • tratamento de reembolso e chargeback.

Tudo isso sob retries, timeouts, duplicação de mensagens e falhas parciais.

Este guia organiza essa complexidade em um design defensável e operável.

Sumário

  • Análise de Requisitos
  • Cálculos de Envelope
  • Arquitetura de Alto Nível
  • Design de API
  • Modelagem de Dados
  • Fluxo de Processamento de Pagamento (Core 1)
  • Ledger de Dupla Entrada (Core 2)
  • Idempotência e Exactly-Once de Negócio (Core 3)
  • Integração com Gateways e Adquirentes
  • Detecção de Fraude
  • Assinaturas e Recorrência
  • Suporte a Multi-Moeda
  • Conciliação Financeira
  • Segurança e Compliance
  • Arquitetura de Banco de Dados
  • Arquitetura Event-Driven
  • Confiabilidade e Tolerância a Falhas
  • Observabilidade e SLOs
  • Dicas para Entrevista
  • Anti-Patterns
  • Conclusão
  • Referências
  • Referência Rápida

Análise de Requisitos

Requisitos Funcionais

  1. Criar intents de pagamento.
  2. Autorizar pagamento em gateway externo.
  3. Capturar pagamento (imediata ou tardia).
  4. Registrar todas as transações em ledger de dupla entrada.
  5. Reembolsar total/parcial.
  6. Tratar chargebacks/disputas.
  7. Suportar webhooks assíncronos idempotentes.
  8. Gerar extratos e relatórios de settlement.
  9. Suportar pagamentos recorrentes.
  10. Suportar várias moedas.

Requisitos Não-Funcionais

Requisito

Meta

Motivo

Disponibilidade API de pagamento

99,99%

impacto direto em receita

Latência auth

< 500ms p99 (fora lat. gateway)

UX de checkout

Durabilidade transacional

perda 0 após ack

confiança e auditoria

Integridade contábil

soma débitos = soma créditos

exigência financeira

Idempotência

retries seguros

rede e provedores são imperfeitos

Auditabilidade

trilha completa e imutável

compliance e disputas

Perguntas de Clarificação

  1. Escopo inclui apenas cartão ou métodos alternativos também?
  2. Captura imediata ou delayed capture?
  3. Subscription está em escopo?
  4. Qual volume de transações por dia?
  5. Precisamos de ledger completo ou apenas registro simplificado?

Premissas do guia:

  • integração com gateways externos,
  • ledger completo,
  • captura flexível,
  • webhooks assíncronos,
  • antifraude e conciliação obrigatórios.

Cálculos de Envelope

Escala Assumida

Transações/dia: 250 milhõesValor médio: USD 32Pico de transações/s (eventos): 25.000Webhooks/dia: 500 milhõesReembolsos/dia: 5 milhõesChargebacks/dia: 300 mil

Throughput

QPS médio tx = 250.000.000 / 86.400 ~= 2.893Pico (8x) ~= 23.144Webhooks/s médio ~= 5.787Pico (6x) ~= 34.722

Armazenamento

Assumindo:

  • payment txn row: 1KB
  • ledger entry row: 500B
  • 4 lançamentos por transação em média

payment rows/dia ~= 250GBledger rows/dia ~= 250M * 4 * 500B ~= 500GBcom réplicas e índices => vários TB/dia

Insight

No sistema de pagamento, o gargalo principal não é CPU de API. É integridade de estado entre:

  • sistema interno,
  • gateway externo,
  • ledger,
  • settlement.

Arquitetura de Alto Nível

flowchart TB subgraph Clientes APP["Checkout Clients"] MER["Merchant Backoffice"] end subgraph Borda API["Payment API Gateway"] AUTH["Auth + Rate Limit"] end subgraph Serviços Core ORCH["Payment Orchestrator"] RISK["Risk/Fraud Engine"] TOKEN["Token Service"] GW["Gateway Connector"] LEDGER["Ledger Service"] REFUND["Refund Service"] SUBS["Subscription Service"] RECON["Reconciliation Service"] WEBHOOK["Webhook Handler"] NOTI["Notification Service"] end subgraph Dados e Plataforma SQL[("Transactional SQL")] LDB[("Ledger Store")] REDIS[("Redis")] KAFKA[("Kafka")] OLAP[("Analytics/Warehouse")] end APP --> API --> AUTH --> ORCH MER --> API ORCH --> RISK ORCH --> TOKEN ORCH --> GW ORCH --> LEDGER GW --> WEBHOOK WEBHOOK --> ORCH WEBHOOK --> LEDGER ORCH --> REFUND ORCH --> SUBS ORCH --> NOTI ORCH --> RECON ORCH --> SQL LEDGER --> LDB RISK --> REDIS ORCH --> KAFKA LEDGER --> KAFKA WEBHOOK --> KAFKA KAFKA --> OLAP

Princípios

  1. Ledger separado de estado de orquestração.
  2. Idempotência de ponta a ponta.
  3. Eventos para desacoplamento e auditoria.
  4. Reconciliação contínua com fontes externas.

Design de API

Endpoints

POST /v1/payment-intentsPOST /v1/payment-intents/{id}/confirmPOST /v1/payment-intents/{id}/capturePOST /v1/payment-intents/{id}/cancelPOST /v1/refundsGET /v1/payments/{payment_id}GET /v1/ledger/accounts/{account_id}/entriesPOST /v1/webhooks/{provider}

Criar Payment Intent

{ "idempotency_key": "9b2f8d8a-78ae-4722-a8c5-88e8ed8f2ca5", "merchant_id": "m_123", "order_id": "ord_901", "amount": { "currency": "USD", "value": 129.99 }, "payment_method": { "type": "CARD_TOKEN", "token": "tok_abc" }, "capture_mode": "MANUAL", "metadata": { "channel": "web" }}

Response:

{ "payment_intent_id": "pi_887", "status": "REQUIRES_CONFIRMATION", "created_at": "2026-02-22T22:10:00Z"}

Confirmar Payment Intent

{ "idempotency_key": "f9d02bc1-61be-4288-a8cd-6d9c8b4a4df0", "payment_intent_id": "pi_887"}

Response:

{ "payment_intent_id": "pi_887", "payment_id": "pay_001", "status": "AUTHORIZED", "authorized_amount": { "currency": "USD", "value": 129.99 }}

Modelagem de Dados

Entidades Principais

  1. PaymentIntent
  2. Payment
  3. PaymentAttempt
  4. LedgerAccount
  5. LedgerEntry
  6. Refund
  7. Dispute
  8. SettlementBatch
  9. ReconciliationRun

Tabelas Core

CREATE TABLE payment_intents ( payment_intent_id VARCHAR(64) PRIMARY KEY, merchant_id BIGINT NOT NULL, order_id VARCHAR(64) NOT NULL, amount_value NUMERIC(20,6) NOT NULL, amount_currency CHAR(3) NOT NULL, status VARCHAR(32) NOT NULL, capture_mode VARCHAR(16) NOT NULL, created_at TIMESTAMP NOT NULL, updated_at TIMESTAMP NOT NULL, UNIQUE (merchant_id, order_id));CREATE TABLE payment_attempts ( payment_attempt_id VARCHAR(64) PRIMARY KEY, payment_intent_id VARCHAR(64) NOT NULL, provider VARCHAR(32) NOT NULL, provider_txn_id VARCHAR(128), status VARCHAR(32) NOT NULL, response_code VARCHAR(32), response_payload JSONB, created_at TIMESTAMP NOT NULL, updated_at TIMESTAMP NOT NULL, UNIQUE (provider, provider_txn_id));

Ledger Schema

CREATE TABLE ledger_accounts ( account_id BIGSERIAL PRIMARY KEY, account_type VARCHAR(32) NOT NULL, currency CHAR(3) NOT NULL, owner_ref VARCHAR(64), status VARCHAR(16) NOT NULL, created_at TIMESTAMP NOT NULL);CREATE TABLE ledger_entries ( entry_id BIGSERIAL PRIMARY KEY, tx_id VARCHAR(64) NOT NULL, account_id BIGINT NOT NULL REFERENCES ledger_accounts(account_id), direction VARCHAR(6) NOT NULL CHECK (direction IN ('DEBIT','CREDIT')), amount NUMERIC(20,6) NOT NULL, currency CHAR(3) NOT NULL, created_at TIMESTAMP NOT NULL);

Regra de Integridade

Para cada tx_id:

SUM(DEBIT) == SUM(CREDIT)

Fluxo de Processamento de Pagamento (Core 1)

Etapas

  1. Validar request e idempotência.
  2. Avaliar risco.
  3. Enviar auth ao gateway.
  4. Persistir resultado local.
  5. Escrever lançamentos no ledger.
  6. Retornar status ao cliente.

Sequência Auth

sequenceDiagram participant C as Client participant P as Payment API participant O as Orchestrator participant R as Risk Engine participant G as Gateway participant L as Ledger C->>P: confirm payment intent P->>O: process request O->>R: risk score R-->>O: allow O->>G: authorize G-->>O: auth approved O->>L: post ledger entries L-->>O: committed O-->>P: AUTHORIZED P-->>C: response

Estados Típicos

  • REQUIRES_CONFIRMATION
  • PROCESSING
  • AUTHORIZED
  • CAPTURED
  • FAILED
  • CANCELED
  • REFUNDED

Ledger de Dupla Entrada (Core 2)

Ledger é o coração de confiabilidade financeira.

Exemplo de Transação de Captura

Para captura de USD 100 com fee USD 3:

  • Débito: clearing account +100
  • Crédito: merchant payable +97
  • Crédito: platform fee revenue +3

Características do Ledger

  1. Append-only.
  2. Imutável (sem update/delete de entry).
  3. Reversão por lançamentos compensatórios.
  4. Índice por tx_id e account_id.

Exemplo de Postagem

{ "tx_id": "tx_445", "entries": [ { "account": "clearing_usd", "direction": "DEBIT", "amount": "100.00", "currency": "USD" }, { "account": "merchant_payable_m123_usd", "direction": "CREDIT", "amount": "97.00", "currency": "USD" }, { "account": "platform_fee_revenue_usd", "direction": "CREDIT", "amount": "3.00", "currency": "USD" } ]}

Reversão

Reembolso não apaga transação anterior. Cria nova transação de sinal oposto.

Idempotência e Exactly-Once de Negócio (Core 3)

Rede e provedores vão duplicar requests. Idempotência é obrigatória.

Tabela

CREATE TABLE idempotency_records ( idempotency_key VARCHAR(64) NOT NULL, merchant_id BIGINT NOT NULL, endpoint VARCHAR(128) NOT NULL, request_hash CHAR(64) NOT NULL, response_code INT NOT NULL, response_body JSONB NOT NULL, created_at TIMESTAMP NOT NULL, expires_at TIMESTAMP NOT NULL, PRIMARY KEY (idempotency_key, merchant_id, endpoint));

Regras

  1. Mesmo key + mesmo hash => replay response.
  2. Mesmo key + hash diferente => 409.
  3. TTL adequado por endpoint (24h–72h).

Webhook Dedupe

async function processWebhook(provider: string, eventId: string, payload: unknown) { const key = `${provider}:${eventId}`; if (await dedupe.exists(key)) return; await db.transaction(async (tx) => { await tx.webhook_events.insert({ provider, event_id: eventId, payload }); await tx.dedupe.insert({ key, ttlHours: 72 }); });}

Integração com Gateways e Adquirentes

Adapter Pattern

Cada provedor tem contrato próprio. Crie camada adaptadora uniforme.

Interface Interna

type GatewayAuthorizeRequest = { amountValue: string; currency: string; token: string; merchantRef: string; idempotencyKey: string;};type GatewayAuthorizeResponse = { approved: boolean; providerTxnId?: string; responseCode: string; requiresAction?: boolean;};

Routing de Gateway

  • roteamento por país/moeda,
  • fallback para segundo gateway,
  • smart retry com limites.

Timeout Policy

  • request timeout estrito,
  • retries idempotentes,
  • classificação de erro (transiente x definitivo).

Detecção de Fraude

Sinais

  1. device fingerprint,
  2. velocity por cartão/conta/IP,
  3. anomalia geográfica,
  4. histórico de chargeback,
  5. score de comerciante.

Decisão

  • allow,
  • challenge,
  • decline,
  • manual review.

Arquitetura

flowchart LR P["Payment Request"] --> F["Feature Fetch"] F --> S["Fraud Scorer"] S --> D["Decision Engine"] D --> A["ALLOW"] D --> C["CHALLENGE"] D --> X["DECLINE"]

Latência

Fraud no caminho crítico precisa budget de milissegundos baixos.

Assinaturas e Recorrência

Requisitos

  1. billing cycles,
  2. retry strategy para falhas,
  3. grace period,
  4. dunning workflow,
  5. cancelamento e prorata.

Ciclo

  1. scheduler gera renewal intent,
  2. tenta charge,
  3. falhou → retry policy,
  4. sucesso → ledger + invoice,
  5. expirou retries → suspende.

Retry Plan Exemplo

T+0, T+1d, T+3d, T+7d

Dados

CREATE TABLE subscriptions ( subscription_id VARCHAR(64) PRIMARY KEY, customer_id BIGINT NOT NULL, plan_id VARCHAR(64) NOT NULL, status VARCHAR(32) NOT NULL, next_billing_at TIMESTAMP NOT NULL, retry_count INT NOT NULL DEFAULT 0, created_at TIMESTAMP NOT NULL, updated_at TIMESTAMP NOT NULL);

Suporte a Multi-Moeda

Desafios

  1. arredondamento,
  2. taxa de câmbio,
  3. ledger por moeda,
  4. settlement cross-border.

Regras

  1. Nunca misturar moedas no mesmo lançamento.
  2. Armazenar valores em decimal exato.
  3. Guardar FX rate usado na conversão.
  4. Separar contas contábeis por moeda.

Exemplo de Conversão

{ "source": { "currency": "EUR", "value": "10.00" }, "target": { "currency": "USD", "value": "10.83" }, "fx_rate": "1.0830", "fx_timestamp": "2026-02-22T21:00:00Z"}

Conciliação Financeira

Conciliação é o mecanismo que detecta divergência entre seu estado e o do provedor.

Tipos

  1. intraday automática,
  2. diária completa,
  3. conciliação de chargeback/refund,
  4. conciliação de payout.

Pipeline

  1. importar arquivo/API de settlement,
  2. normalizar para schema interno,
  3. comparar com pagamentos/ledger,
  4. classificar discrepâncias,
  5. abrir casos de remediação.

Resultado de Conciliação

{ "run_id": "recon_2026_02_22", "provider": "gateway_x", "matched": 24900123, "missing_internal": 123, "missing_provider": 77, "amount_mismatch": 44, "status": "COMPLETED"}

SLA

Sem conciliação, incidente financeiro pode ficar oculto por dias.

Segurança e Compliance

Segurança

  1. TLS e mTLS interno em domínios sensíveis.
  2. tokenização de cartão.
  3. HSM/KMS para chaves criptográficas.
  4. segregação de ambientes e segredos.
  5. auditoria de acesso privilegiado.

PCI DSS

Objetivo prático:

  • minimizar escopo PCI,
  • evitar armazenar PAN bruto,
  • usar provedores/token vault certificados.

Privacidade

  • minimização de PII,
  • retenção por requisito legal,
  • anonimização quando possível,
  • trilha de consentimento.

Arquitetura de Banco de Dados

Mapeamento por Domínios

Domínio

Store

intents/payments

SQL transacional

ledger

SQL append-only ou store contábil dedicado

idempotency/dedupe

SQL ou KV forte

risk cache

Redis

analytics

OLAP/Warehouse

Sharding

  • por merchant_id para isolamento,
  • ou hash(payment_id) para distribuição uniforme,
  • com índices secundários para consultas operacionais.

Evolução de Schema

  1. adicionar campo opcional,
  2. backfill,
  3. dual-read,
  4. switch writer,
  5. remover legado.

Arquitetura Event-Driven

Eventos Core

  • PaymentIntentCreated
  • PaymentAuthorized
  • PaymentCaptured
  • PaymentFailed
  • RefundIssued
  • ChargebackOpened
  • ChargebackResolved
  • SettlementImported
  • ReconciliationCompleted

Diagrama

flowchart TB ORCH["Orchestrator"] --> BUS["Kafka"] LED["Ledger"] --> BUS WEB["Webhook Handler"] --> BUS REF["Refund Service"] --> BUS BUS --> REC["Reconciliation"] BUS --> NOTI["Notifications"] BUS --> DWH["Analytics"] BUS --> AUD["Audit Pipeline"]

Outbox

Garantir publish confiável junto da transação local.

CREATE TABLE outbox_events ( event_id UUID PRIMARY KEY, aggregate_type VARCHAR(32) NOT NULL, aggregate_id VARCHAR(64) NOT NULL, event_type VARCHAR(64) NOT NULL, payload JSONB NOT NULL, created_at TIMESTAMP NOT NULL, published_at TIMESTAMP);

Confiabilidade e Tolerância a Falhas

Falhas Clássicas

  1. timeout no gateway com status desconhecido,
  2. webhook duplicado/atrasado,
  3. ledger indisponível,
  4. fila com lag,
  5. erro de conciliação.

Estratégias

  1. idempotência em todas as mutações,
  2. timeouts + retries com jitter,
  3. circuit breakers,
  4. fallback para estado PENDING_EXTERNAL_CONFIRMATION,
  5. replay de eventos.

Estado "Desconhecido"

Quando timeout no gateway sem resposta conclusiva:

  • marcar tentativa como UNKNOWN,
  • consultar status assíncrono,
  • bloquear duplicidade via idempotency,
  • atualizar estado final após confirmação.

SLA de Recovery

  • caminhos de autorização/captura devem recuperar rápido,
  • processos de conciliação podem ter janelas maiores,
  • sem perder audit trail.

Observabilidade e SLOs

SLOs

Serviço

SLI

SLO

Payment confirm

p99 latência

< 500ms (sem rede externa)

Auth success

taxa de sucesso

dentro da baseline por método

Webhook processing

atraso p95

< 30s

Ledger posting

durabilidade

perda 0

Reconciliation

execução diária

100% runs concluídas

Golden Signals

Orchestrator:

  • success/failure rate,
  • timeout externo,
  • idempotency replay,
  • latency p95/p99.

Ledger:

  • post failures,
  • imbalance detector,
  • write latency.

Webhook:

  • dedupe hit rate,
  • processing lag,
  • invalid signature rate.

Correlação

x-request-idx-payment-intent-idx-payment-attempt-idx-ledger-tx-idx-provider-txn-id

Dicas para Entrevista

Estrutura de Resposta

  1. Defina escopo (auth/capture/refund/ledger).
  2. Faça estimativa de volume.
  3. Desenhe arquitetura macro.
  4. Deep dive em idempotência e ledger.
  5. Explique webhooks e conciliação.
  6. Feche com compliance e SLOs.

Erros Comuns

  1. ignorar ledger de dupla entrada,
  2. tratar retry sem idempotência,
  3. sem plano para status desconhecido,
  4. sem conciliação,
  5. sem separação entre estado de negócio e estado externo.

Tabela de Trade-offs

Decisão

Opção A

Opção B

Recomendado

registro financeiro

saldo mutável

ledger append-only

append-only

retries

sem chave

idempotência forte

idempotência forte

webhook

best effort

dedupe + assinatura + replay

dedupe + replay

gateway

único provedor

multi-provider

multi-provider (complexidade controlada)

conciliação

manual eventual

pipeline automatizada

automatizada

Anti-Patterns

1) Atualizar saldo direto sem ledger

Problema: sem trilha auditável e alta chance de inconsistência.

Correção: dupla entrada append-only.

2) Retry sem idempotency key

Problema: cobrança duplicada.

Correção: chave obrigatória por mutação.

3) Confiar cegamente no status síncrono

Problema: timeout gera incerteza e duplicidade.

Correção: estado pendente + confirmação assíncrona.

4) Ignorar webhooks duplicados

Problema: transições repetidas e estado corrompido.

Correção: dedupe por provider event id.

5) Sem conciliação diária

Source

1 share