Papers
Ledger: Stripe's System for Tracking and Validating Money Movement
Ilya Ganelin · Stripe Dot Dev Blog (post de engenharia, não revisado por pares), 2024
O problema: provar que sistemas independentes fecham a conta juntos
A rede de pagamentos e tesouraria da Stripe aceita pagamentos, guarda dinheiro e o movimenta entre muitas moedas e meios de pagamento, por meio de parceiros bancários e redes financeiras locais. Para tornar o problema tratável, a plataforma é dividida em serviços, bancos de dados e interfaces (APIs/gRPC) distintos. O custo dessa divisão é que nada força esses sistemas a representar ou entregar dados do mesmo jeito: alguns operam em tempo real e outros em cadência mensal; alguns geram bilhões de eventos por dia e outros apenas algumas centenas; e cada um tem a sua própria definição de correção. Mesmo assim, a Stripe precisa garantir, para clientes internos e auditores externos, que o que deveria acontecer no processamento de pagamentos de fato acontece. O post resume a necessidade como um mecanismo capaz de lidar com essas variações e provar que os sistemas individuais, em conjunto, modelam corretamente as finanças da empresa. O texto também enfatiza que o mundo real é imperfeito: relatórios malformados, erros propagados por parceiros bancários ou de rede e até mudanças macroeconômicas. Embora aspire a um ideal ordenado, a Stripe diz que, na sua escala, isso é impossível; em vez disso, construiu um sistema que mantém essas imperfeições gerenciáveis e delimitadas. Ledger e uma plataforma de Data Quality construída sobre ele são a resposta.
A ideia central: sistemas modelados como fluxos de fundos entre contas
O Ledger representa cada sistema produtor como uma máquina de estados e descreve seu comportamento como um fluxo lógico de fundos: saldos (eventos) que se movem entre contas (estados). A partir disso, o Ledger calcula todos os saldos de conta, agrupados por várias subdivisões, para avaliar a saúde do sistema e gerar estatísticas. Contas são baldes de dinheiro distinguidos por tipo (por exemplo, charge_unsubmitted) e por propriedades (por exemplo, id e business); eventos movem dinheiro entre contas. Uma cobrança, por exemplo, aparece como um evento de criação, para a cobrança pendente, e um evento de liberação, quando ela se completa. O Ledger funciona como um repositório semântico: em vez de calcular um dataset derivado de pipelines de entrada, ele modela o trabalho real dos sistemas produtores, registrando cada operação como uma transação. Como esse modelo pode divergir dos dados de origem, o post diz que a divergência é vigiada explicitamente por verificações de completude. Como o Ledger é um sistema de registro em nível de transação, ele também modela a consistência entre sistemas desconectados e acompanha cada transação por todo o seu ciclo de vida, o que o post chama de tracing. Um fluxo de ponta a ponta, como uma empresa adicionar fundos ao seu saldo, atravessa várias equipes, e modelá-lo como fluxo unifica esses dados.
Partidas dobradas: o erro vira saldo que não zerou
O Ledger é baseado em contabilidade de partidas dobradas, um método padrão para garantir que todo o dinheiro de um sistema está contabilizado, equilibrando créditos e débitos. O post usa uma analogia: o fluxo de água por uma rede de canos (processos) que termina em reservatórios (balanços). Em regime estável, os reservatórios terminais estão cheios e os canos intermediários (contas de clearing) estão vazios; água presa nos canos, isto é, saldo não resolvido, indica um problema. A Stripe aplica a ideia além do dinheiro físico, para modelar comportamentos de sistemas como conversão de moeda, leitura de relatórios, estimativas e análise de cobrança. No exemplo do post, o evento charge.creation cria saldo numa conta de valores ainda não desembolsados e, depois, charge.release move os fundos para o saldo da empresa. Os dois eventos são independentes: mesmo que cheguem fora de ordem ou de fontes diferentes, o Ledger os une pelos identificadores business e id. Se a liberação nunca for publicada ou vier com id errado, o saldo da conta intermediária não zera. Do mesmo modo, um valor business errado (B em vez de A) deixa duas contas com saldo diferente de zero em vez de uma. Assim, um evento ausente, atrasado ou incorreto é detectado com uma consulta simples, como achar as contas de clearing com saldo não nulo.
Imutabilidade, correção de dados e o que o post não diz sobre idempotência
No núcleo, o Ledger é um log imutável de eventos. Transações já publicadas não podem ser apagadas nem modificadas, e o estado passado pode sempre ser reconstruído processando os eventos até aquele ponto. Saldos, fluxos de fundos e controles de qualidade de dados são todos transformações dessa estrutura estática, o que permite auditar e reproduzir qualquer dado a qualquer momento e analisar exatamente o dado problemático. O outro lado da moeda é que não se corrige o estado com uma consulta que altera registros: é preciso reverter e reprocessar operações anteriores. Para isso a Stripe construiu um utilitário que cria e executa migrações com segurança, protegido por uma ferramenta de qualidade de dados que gera relatórios out-of-band (fora do fluxo de execução) sobre o impacto em produção das mudanças propostas. Juntas, essas ferramentas aproximam um pipeline de CI para reparos pontuais, e toda operação passa por revisão e commit em duas fases, tanto do dado quanto do impacto em DQ. Uma ressalva de escopo: o post não discute idempotência nem como escritas duplicadas são tratadas, então este resumo não atribui nenhum mecanismo desse tipo à Stripe. O que o texto estabelece são ingredientes vizinhos, o log imutável, a derivação dos saldos a partir dele e o reprocessamento de eventos.
Plataforma de Data Quality: clearing, timeliness e completeness
Sobre o Ledger, a Stripe construiu uma plataforma de Data Quality (DQ) que avalia cada fluxo de fundos com três perguntas. Clearing: o fluxo se completou corretamente? É verificado pelas contas de clearing que deveriam estar zeradas. Timeliness: os dados chegaram a tempo? Mede-se o intervalo entre o dado entrar na plataforma Stripe e chegar ao Ledger, contra um limite rígido de janela de entrega. Completeness: temos uma representação completa do sistema de origem? Isso usa checagens entre sistemas (por exemplo, todo ID no banco do produtor deve ter um evento correspondente no Ledger), detecção automática de anomalias e modelos estatísticos por tipo de conta que estimam, pelo histórico, quando os dados deveriam chegar; evento que não aparece é tratado como possível dado faltante. As métricas se compõem num score de DQ unificado, e o post afirma que um sistema com 99,99% de score dificilmente esconde problemas graves. O post reporta cerca de cinco bilhões de eventos por dia no Ledger, 99,99% do volume em dólares totalmente ingerido e verificado em até quatro dias, e mais de 99,9999% de explicabilidade da movimentação de dinheiro, mesmo com o volume de dados tendo crescido 10 vezes. Painéis mostram o score por equipe, com tickets gerados automaticamente, e permitem investigar um ponto do gráfico até a causa raiz.
Veja as ideias em ação
Pratique na escola de System Design os desenhos que usam este paper.