Sou formado em engenharia de produção, e uma das matérias base do curso é metrologia, a ciência das medições. Na época parecia a disciplina mais burocrática da grade: norma, certificado, laboratório acreditado, planilha de incerteza. Hoje trabalho com pagamentos na Woovi, e várias decisões de arquitetura que a gente toma são, no fundo, o mesmo problema que a metrologia resolve há décadas.
A ligação é a seguinte: perguntar “esse pagamento foi confirmado?” é fazer uma medição. Você não observa o fato diretamente, observa o que algum instrumento te reporta. E quando existe um intermediário entre a sua aplicação e a fonte de verdade (no Pix, o Banco Central), você está na mesma situação de um laboratório que calibra o instrumento contra um padrão, que foi calibrado contra outro padrão, que foi calibrado contra outro.
Neste post vou explicar como a metrologia trata erro e calibração, e depois usar esses conceitos para olhar a arquitetura de um sistema de pagamentos, principalmente o que muda quando o gateway que você usa não tem conexão direta com o Bacen.
Erro de medição
O primeiro conceito é que valor verdadeiro é inatingível. Você nunca mede a massa de um objeto, você mede o que a balança indica, que é o valor verdadeiro somado a um erro que você não conhece.
valor indicado = valor verdadeiro + erroComo o erro é desconhecido, o que se faz na prática é estimar um intervalo onde o valor verdadeiro provavelmente está. Isso é a incerteza de medição, e é por isso que um certificado de calibração nunca diz “a peça mede 10 mm”, e sim algo como:
10,002 mm ± 0,003 mm (k = 2, ~95% de confiança)O ± 0,003 faz parte do resultado. Sem ele, o 10,002 não permite decidir nada, porque você não sabe se a peça está dentro ou fora da tolerância do projeto.
Os erros se dividem em dois tipos, e essa separação importa bastante:
- Erro sistemático: sempre na mesma direção. Uma balança descalibrada que marca 2 g a mais em toda pesagem. Dá para corrigir, se você conhecer o valor.
- Erro aleatório: varia a cada medição, ora para cima, ora para baixo. É ruído. Não dá para corrigir, mas dá para reduzir repetindo a medição e tirando a média.
Tratar erro sistemático como se fosse aleatório é o erro clássico: você repete a medição mil vezes e a média converge com ótima precisão para o valor errado.
A cadeia de rastreabilidade
Como você sabe que a sua balança está certa? Comparando com um padrão. E como você sabe que o padrão está certo? Comparando com um padrão melhor. Isso se repete até chegar na definição do SI.
Esse encadeamento tem nome: cadeia de rastreabilidade metrológica. É uma sequência ininterrupta de calibrações ligando o instrumento que está no chão de fábrica até o padrão primário.
flowchart TB SI["Definição SI<br/>(BIPM)"] NMI["Padrão nacional<br/>(Inmetro)"] Lab["Laboratório acreditado<br/>(RBC)"] Interno["Padrão interno<br/>da empresa"] Inst["Instrumento de trabalho<br/>(chão de fábrica)"] SI -->|u1| NMI NMI -->|u2| Lab Lab -->|u3| Interno Interno -->|u4| Inst
Cada seta é uma calibração, e cada calibração adiciona incerteza. Não existe elo que melhore a precisão do anterior: o melhor que um elo faz é degradar pouco.
Como o erro se acumula
Para contribuições independentes, a incerteza combinada é a soma em quadratura:
u_c = sqrt(u1² + u2² + u3² + u4²)A consequência prática disso é que a maior contribuição domina o resultado. Com u1 = 0,1, u2 = 0,1, u3 = 0,1 e u4 = 1,0, a combinada dá 1,015. Zerar completamente os três primeiros elos levaria o total para 1,0. Todo o esforço, e o ganho é de 1,5%.
Isso vale para erros independentes. Se as contribuições forem correlacionadas (todos os elos usando o mesmo padrão enviesado, ou todos medindo no mesmo ambiente com temperatura fora da faixa), elas somam linearmente:
u_c = u1 + u2 + u3 + u4O acúmulo fica muito pior. Erro correlacionado é o problema mais chato da cadeia, porque você acha que está somando ruído quando na verdade está somando bias.
Existe uma regra prática de calibração industrial chamada TUR (test uncertainty ratio): o padrão usado precisa ser pelo menos 4 vezes mais preciso que a tolerância que você quer garantir. Para tolerância de ± 0,1 mm, o padrão precisa de incerteza melhor que 0,025 mm. Medir com precisão parecida com a tolerância é praticamente não medir.
Calibração não elimina erro
Calibrar não deixa o instrumento perfeito. Calibrar é levantar o erro dele em pontos específicos da faixa e, quando dá, corrigir o bias. Um instrumento calibrado não é um que não erra, é um que erra de forma conhecida e documentada.
Isso muda três coisas na operação: você sabe em qual faixa confiar no instrumento, sabe que ele deriva com o tempo e precisa voltar para o laboratório, e sabe se o erro atual é aceitável para a decisão que você vai tomar com aquele número.
O elo mais fraco
Vale registrar uma coisa antes de ir para pagamentos, porque não é sobre paquímetro. O que está descrito acima é um modelo de sistema em série, e ele reaparece com outros nomes em quase toda disciplina de engenharia de produção:
- Na Teoria das Restrições, a capacidade da linha é a capacidade do gargalo. Investir na estação mais rápida não aumenta um item na saída.
- Em gestão de projetos, o prazo é o caminho crítico. Adiantar tarefa fora dele não antecipa a entrega.
- Em cadeia de suprimentos, a fábrica para por causa do fornecedor que quebrou, não da média dos fornecedores.
- Em confiabilidade, componentes em série têm disponibilidade igual ao produto das disponibilidades, sempre menor que a do pior.
- Em rendimento de processo, o rolled throughput yield é o produto dos rendimentos de cada etapa.
Em todos esses casos a matemática tem a mesma cara: você compõe as contribuições de cada elo (somando incertezas, multiplicando disponibilidades, multiplicando rendimentos) e o resultado é sempre pior do que qualquer elo isolado. Composição em série nunca melhora o todo.
Daí sai a parte que interessa na prática: como o pior elo domina, otimizar qualquer outro é desperdício. Em produção isso se aprende cedo porque errar custa caro, a fábrica que investiu na estação errada continua com o mesmo throughput e um capital a menos.
A força do sistema é a força do elo mais fraco. O trabalho de engenharia é descobrir qual é esse elo, e isso é uma pergunta de medição, não de opinião.
Gateways de pagamento
Trocando “medição” por “estado de um pagamento” e “cadeia de rastreabilidade” por “cadeia de liquidação”, a estrutura é a mesma.
No Pix, a fonte de verdade é o SPI (Sistema de Pagamentos Instantâneos), operado pelo Banco Central. Um pagamento está liquidado quando o SPI diz que está. Não quando o seu backend diz, não quando o gateway diz.
Só que nem todo mundo fala com o SPI. Para conectar direto é preciso ser participante direto: autorização do Bacen, infraestrutura na RSFN, certificados ICP-Brasil, atender aos requisitos de disponibilidade e de compliance da regulação. É caro, é demorado, e a maior parte das empresas não tem como fazer isso.
Então o mercado se organizou em camadas. Quem não é participante direto se pluga em quem é.
flowchart TB Bacen["Banco Central<br/>SPI / DICT"] Direto["Participante direto<br/>(instituição autorizada)"] Indireto["Participante indireto / PSP<br/>(liquida via o direto)"] Gw["Gateway / orquestrador<br/>(camada de API)"] App["Sua aplicação"] Bacen -->|RSFN| Direto Direto -->|contrato + API| Indireto Indireto -->|API| Gw Gw -->|webhook + API| App
É o mesmo desenho da cadeia de rastreabilidade, e vale a mesma regra: nenhum elo melhora a garantia do anterior.
O que muda de uma cadeia para a outra é o que se acumula. Na metrologia acumula incerteza de medição. Aqui acumulam quatro coisas ao mesmo tempo: latência (cada hop custa tempo de rede), indisponibilidade (cada hop pode cair sozinho), divergência de estado (cada hop tem sua própria cópia do estado) e risco regulatório (cada hop responde a um contrato e a um regulador diferentes). As duas primeiras todo mundo considera. As duas últimas são as que costumam quebrar sistema em produção.
Disponibilidade composta
Se cada elo tem disponibilidade independente, a disponibilidade fim a fim é o produto delas:
A_total = A1 × A2 × A3 × A4Com números plausíveis:
| Cadeia | Cálculo | Disponibilidade | Indisponibilidade/mês |
|---|---|---|---|
| Direto no participante autorizado | 99,95% | 99,95% | ~22 min |
| Participante + PSP indireto | 99,95% × 99,9% | 99,85% | ~65 min |
| Participante + PSP + gateway | 99,95% × 99,9% × 99,9% | 99,75% | ~108 min |
| Participante + PSP + gateway + orquestrador | 99,95% × 99,9% × 99,9% × 99,9% | 99,65% | ~151 min |
Cada camada adicional custa por volta de 43 minutos de indisponibilidade por mês, mesmo que cada uma delas pareça excelente isoladamente. É o mesmo fenômeno do acúmulo de incerteza: você não consegue ser mais confiável que o produto dos seus elos.
O pior elo domina aqui também. Um gateway com 99,5% na frente de um participante com 99,95% resulta em 99,45%. Nesse cenário, melhorar a sua aplicação de 99,99% para 99,999% não muda nada no número que o seu cliente enxerga. É a estação rápida sendo otimizada enquanto o gargalo continua parado.
A conta acima assume falhas independentes. Se dois gateways diferentes liquidam pelo mesmo participante direto, eles não são redundantes: quando o participante cai, os dois caem junto. É exatamente o erro correlacionado da metrologia, que soma linear em vez de em quadratura.
O estado não é o mesmo em todo lugar
Esse é o problema mais silencioso da cadeia. Cada elo guarda uma cópia do estado do pagamento, e essas cópias não mudam ao mesmo tempo.
sequenceDiagram participant SPI as SPI (Bacen) participant PD as Participante direto participant GW as Gateway participant App as Sua aplicação SPI->>PD: liquidado em T0 Note over PD: estado atualizado em T0 + 200ms PD->>GW: notificação Note over GW: estado atualizado em T0 + 900ms GW-->>App: webhook Note over App: estado atualizado em T0 + 2s<br/>(ou nunca, se o webhook falhar)
Entre T0 e o momento em que a sua aplicação atualiza existe uma janela onde você tem uma medição desatualizada sem saber disso. Se o webhook se perder, essa janela não fecha.
Os modos de falha dessa janela são conhecidos por quem trabalha com pagamento:
- Webhook perdido: o pagamento liquidou, o cliente pagou, e o seu sistema nunca soube. O cliente aparece no suporte com o comprovante na mão.
- Webhook duplicado: a mesma notificação chega duas vezes por retry. Sem idempotência, você credita duas vezes.
- Webhook fora de ordem: chega
CONFIRMEDdepois deEXPIRED, porque foram por rotas diferentes. - Timeout ambíguo: você pediu a criação de uma cobrança, deu timeout, e não sabe se ela existe do outro lado. É o pior tipo de erro, o que não te diz se aconteceu.
Repare que nada disso é erro aleatório. É erro sistemático. Consultar o mesmo gateway de novo não ajuda, porque se ele tem o estado errado ele vai devolver o estado errado de forma bem consistente. Para corrigir bias é preciso medir contra um padrão de nível superior.
Regulatório e compliance
Existe um risco em metrologia que não é técnico: o laboratório que calibra o seu padrão pode perder a acreditação. Da noite para o dia todos os certificados que ele emitiu ficam questionáveis e a sua cadeia de rastreabilidade fica inválida, mesmo com os instrumentos fisicamente perfeitos.
Na cadeia de pagamentos acontece a mesma coisa, e essa é a categoria de risco que menos aparece nas comparações de gateway:
- Quem responde ao Bacen é o participante direto. Se ele sofre sanção, tem a autorização suspensa ou entra em regime especial, todo mundo pendurado nele para de operar. Você não fez nada e mesmo assim está fora do ar.
- O contrato que sustenta a sua operação não é seu. O acordo entre o participante direto e o PSP intermediário pode mudar sem você participar da conversa. Uma mudança de política de risco em um elo que você nem conhece derruba o seu fluxo.
- Requisito novo desce a cadeia com atraso. Uma exigência do Bacen chega ao participante direto, que repassa ao PSP, que repassa ao gateway, que precisa expor aquilo na API para você conseguir cumprir. Cada tradução perde informação, e o prazo de adequação continua sendo o original.
- Compliance vira caixa preta. Quando o seu cliente é bloqueado por análise de risco, quem tomou a decisão? Em uma cadeia de quatro elos, descobrir isso vira um processo de dias por email, sobre uma regra que afeta diretamente a sua receita.
- A superfície de dados aumenta. Dados de transação e dados pessoais passam por mais um terceiro. Para LGPD, cada intermediário é mais um operador no fluxo, mais um contrato, mais um lugar para auditar e mais um ponto de vazamento possível.
- A custódia do dinheiro fica confusa. Entre a liquidação e o repasse para você, o recurso fica em conta de quem exatamente? Em cadeia longa a resposta costuma ser “de alguém no meio”, e o risco de crédito desse elo é seu.
Calibrando o sistema
A resposta da metrologia para “meu instrumento tem erro” nunca foi jogar o instrumento fora. Foi conhecer o erro, corrigir o bias, monitorar a deriva e recalibrar de tempos em tempos. Aqui funciona igual: o problema não é usar gateway, é usar sem medir.
Escolha o padrão de referência
Você precisa definir qual fonte é a verdade do seu sistema, e ela não pode ser o seu próprio banco. Na prática o mais próximo que dá para chegar é o extrato do participante direto, que é o elo mais perto do SPI ao qual você tem acesso.
Todo o resto (resposta de API, webhook, cache) é medição, está sujeita a erro e precisa ser conferida contra esse padrão periodicamente.
Reconciliação é calibração
Reconciliar não é tarefa contábil, é a calibração do sistema. Ela responde exatamente a pergunta metrológica: qual o erro atual da minha medição em relação ao padrão?
flowchart LR Extrato["Extrato do participante<br/>(padrão de referência)"] DB["Estado no seu banco<br/>(instrumento)"] Diff["Diff"] Metric["Métrica de divergência<br/>+ alerta"] Extrato --> Diff DB --> Diff Diff --> Metric
E o resultado precisa virar número, do mesmo jeito que um certificado de calibração vira número:
# HELP payments_reconciliation_divergence_total Divergências entre estado local e extrato# TYPE payments_reconciliation_divergence_total counterpayments_reconciliation_divergence_total{type="missing_locally",provider="gw_a"} 12payments_reconciliation_divergence_total{type="missing_upstream",provider="gw_a"} 0payments_reconciliation_divergence_total{type="amount_mismatch",provider="gw_a"} 1
# HELP payments_state_lag_seconds Atraso entre liquidação na origem e atualização local# TYPE payments_state_lag_seconds histogrampayments_state_lag_seconds_bucket{le="1",provider="gw_a"} 8420payments_state_lag_seconds_bucket{le="5",provider="gw_a"} 9910payments_state_lag_seconds_bucket{le="30",provider="gw_a"} 9998payments_state_lag_seconds_bucket{le="+Inf",provider="gw_a"} 10000Com o label provider você consegue comparar provedores entre si e alertar quando um deles começa a derivar. Sem essas métricas você não sabe o erro do instrumento, apenas confia nele.
Webhook não é fonte de verdade
Webhook é push: sem garantia de entrega, de ordem ou de unicidade. Ele serve para reduzir latência, avisando que alguma coisa mudou. A correção vem da consulta e da reconciliação.
async function onWebhook(event: GatewayEvent) { // sem validar assinatura, o sensor aceita qualquer entrada if (!verifySignature(event)) return reject()
// idempotência pela chave do provedor, não por id gerado localmente if (await alreadyProcessed(event.endToEndId)) return ack()
// não confia no payload: reconsulta o estado na origem const state = await gateway.getCharge(event.chargeId)
// transição só avança, nunca regride await applyStateTransition(event.chargeId, state)
return ack()}Os três pontos que mais evitam dor de cabeça:
- Idempotência pela chave de negócio do provedor. No Pix o
endToEndIdé estável ao longo de toda a cadeia, então ele funciona como chave mesmo se o pagamento passar por vários elos. - Reconsultar em vez de confiar no corpo do webhook, que pode estar defasado até em relação ao próprio gateway que o enviou.
- Máquina de estados monotônica. Uma cobrança que já está
CONFIRMEDnão volta paraPENDINGporque chegou um evento antigo. É o equivalente a rejeitar leitura fora da faixa do instrumento.
Meça cada elo separadamente
Em metrologia, decompor a incerteza serve para saber qual contribuição atacar. Aqui é a mesma coisa: medir só a latência fim a fim não diz onde investir.
Instrumentando por hop, com provider como label, aparecem coisas como “o gateway responde em 80 ms mas o participante atrás dele leva 1,2 s”. Sem essa decomposição você não sabe qual é o elo mais fraco, e sem saber qual é o elo mais fraco toda otimização vira aposta.
Faça a conta antes de escolher
Antes de assinar com um gateway, dá para fazer o mesmo cálculo que um metrologista faria, que é verificar se a incerteza total cabe na tolerância:
- Esse provedor é participante direto? Se não for, quantos elos existem entre ele e o SPI? Vale perguntar isso explicitamente, porque é comum um produto se descrever como “conexão Pix” sem deixar claro que liquida por três camadas.
- Qual disponibilidade eu preciso entregar para o meu cliente?
- Multiplicando os SLAs de toda a cadeia, eu chego nesse número?
- Quem é o participante direto na ponta? É o mesmo dos meus outros provedores?
- O que esse intermediário me entrega que compensa os elos que ele adiciona?
A lógica do TUR se aplica bem aqui. Se você precisa entregar 99,9% e escolhe um caminho que entrega 99,9% no melhor cenário, é o mesmo que medir tolerância de 0,1 mm com um instrumento de 0,1 mm de incerteza. Precisa de folga.
Redundância só vale se for independente
Ter dois gateways parece redundância, mas se os dois liquidam pelo mesmo participante direto o modo de falha é comum. Redundância de verdade exige caminhos que separam o mais perto possível da origem.
flowchart TB SPI["SPI"] P1["Participante A"] P2["Participante B"] G1["Gateway 1"] G2["Gateway 2"] App["Sua aplicação"] SPI --> P1 SPI --> P2 P1 --> G1 P2 --> G2 G1 --> App G2 --> App
Se os dois caminhos convergem em um único participante antes do Bacen, você tem duas integrações para manter e um ponto único de falha.
O custo de manter vários provedores
Essa é a saída mais comum de quem usa gateway. Como cada provedor sozinho não entrega a disponibilidade necessária, contrata-se dois ou três e coloca-se uma camada de roteamento na frente, que troca de rota quando um começa a falhar. Em confiabilidade isso é redundância paralela, e funciona: com dois caminhos independentes de 99,75%, a indisponibilidade dos dois ao mesmo tempo cai para 0,0006%.
O problema é que a conta de disponibilidade melhora e a de complexidade piora, e a segunda ninguém coloca na planilha antes de decidir:
- Cada provedor tem o seu modelo. Nomes de estado diferentes, códigos de erro diferentes, formato de webhook diferente, política de retry diferente. Você acaba escrevendo uma camada de tradução para um estado interno canônico, e essa camada vira o lugar onde os bugs aparecem.
- A reconciliação multiplica. Cada provedor tem seu extrato, seu horário de fechamento e seu jeito de identificar a transação. Reconciliar dois é mais que o dobro do trabalho de reconciliar um, porque agora existe o caso de a cobrança ter sido criada em um e paga pelo outro.
- O roteamento precisa de estado. Decidir qual provedor usar exige saber a saúde de cada um em tempo real, ter health check, circuit breaker e critério de volta. Roteador mal calibrado derruba tráfego bom ou insiste em rota morta.
- O failover em cima de operação em andamento é o caso difícil. Trocar de rota é simples para uma cobrança nova. Para uma cobrança já criada no provedor que caiu, não é: ela existe lá, pode ser paga a qualquer momento e continua sendo responsabilidade sua.
- A superfície de teste cresce junto. Sandbox de cada provedor, comportamento de cada um em timeout, e o cenário de failover, que é justamente o mais difícil de reproduzir e por isso quase nunca é testado.
O resultado é que você troca um problema de confiabilidade por um problema de engenharia, e passa a manter internamente algo parecido com um orquestrador de pagamentos. Para operação grande isso se paga. Para time pequeno costuma sair mais caro do que aparenta, e é bom notar que boa parte desse trabalho existe para compensar a instabilidade que os elos extras introduziram.
Vale a mesma ressalva do erro correlacionado: dois provedores só melhoram a disponibilidade se forem independentes de verdade. Se ambos liquidam pelo mesmo participante direto, você pagou todo esse custo de complexidade e continua com um ponto único de falha.
Resumo do paralelo
| Metrologia | Pagamentos |
|---|---|
| Valor verdadeiro | Estado no SPI |
| Medição | Resposta de API ou webhook do gateway |
| Cadeia de rastreabilidade | Cadeia de liquidação (Bacen → direto → PSP → gateway) |
| Cada elo adiciona incerteza | Cada elo adiciona latência, queda e risco |
| Erro sistemático | Estado divergente, webhook perdido, defasagem |
| Erro aleatório | Timeout esporádico, jitter de rede |
| Erros correlacionados somam linearmente | Gateways que compartilham o mesmo participante direto |
| Calibração periódica | Reconciliação contra o extrato da origem |
| Certificado com incerteza declarada | SLA composto, medido por provedor |
| Laboratório perde a acreditação | Participante direto sancionado ou te desligando |
| TUR 4:1 | Folga entre o SLA da cadeia e o que você promete |
| Gargalo define a capacidade da linha | Elo mais fraco define o SLA que você entrega |
Conclusão
A variável que mais mexe no resultado final é o número de elos entre você e o SPI, e ela costuma ser decidida sem análise nenhuma. Escolhe-se um provedor pela documentação, pela taxa ou por indicação, e a topologia da cadeia vem junto no pacote sem ninguém perguntar.
Vale separar duas coisas aqui. Ser participante direto você provavelmente não vai ser, porque exige autorização, infraestrutura na RSFN e um custo de compliance que só se paga em escala grande. Mas saber se o seu provedor é um, e o que existe atrás dele quando não é, é pergunta de contrato e não de engenharia. Está ao alcance de qualquer empresa fazer.
Voltando à conta: cada camada intermediária custa cerca de 43 minutos de indisponibilidade por mês, uma cópia a mais do estado do pagamento para divergir, um hop a mais de rede e fila em cima do tempo de confirmação, e mais um contrato entre você e quem responde ao Bacen. Nenhuma delas devolve nada em precisão ou em velocidade, porque composição em série não melhora o todo. Elas se pagam por outras coisas, como conveniência de integração, meios de pagamento adicionais ou antifraude embutido, e é exatamente essa troca que precisa ser explícita na hora de escolher.
Reparei que essa troca costuma ser paga duas vezes. Primeiro na cadeia mais longa, depois na multiplicação de provedores que se contrata para compensar a instabilidade que ela trouxe. Roteamento, tradução de estado, reconciliação por provedor e teste de failover são código que só existe por causa dos elos extras, e mantê-lo é trabalho recorrente de um time que provavelmente preferia estar resolvendo outra coisa. Encurtar a cadeia resolve o mesmo problema pelo outro lado, sem código nenhum.
Quando a cadeia longa for a opção certa, o resto do post vale igual: reconcilie contra a fonte mais próxima da origem que você alcançar, meça a divergência por provedor e prometa ao seu cliente menos do que o SLA composto da sua cadeia.
O modelo que descrevi aqui não é da metrologia, ela só é uma das áreas que o formaliza bem. Gargalo, caminho crítico, cadeia de rastreabilidade e cadeia de liquidação são o mesmo objeto visto por janelas diferentes, e em todos eles a força do sistema é a força do elo mais fraco. Vale mais aprender a reconhecer esse padrão do que decorar as fórmulas de cada área isoladamente, porque quando você troca de contexto o modelo vai junto.
Referências
- BIPM — Guide to the Expression of Uncertainty in Measurement (GUM)
- Inmetro — Vocabulário Internacional de Metrologia (VIM)
- Banco Central — Pix e modalidades de participação
- Banco Central — Regulamento do Pix
- Manual de Padrões para Iniciação do Pix
- Métricas do Prometheus no /metrics e quando usar cada uma — sobre os tipos de métrica usados na reconciliação