Como eu desenharia um sistema de PIX que aguenta 10 tps

Uma conversa simulada entre gerência e engenharia — e o capítulo que eu escreveria depois, com analogias do dia a dia.

Quatro camadas, um objetivo: dinheiro em movimento sem perda, duplicidade ou queda em cascata.

Pergunta do gerente

Cenário simulado · entrevista de arquitetura

Suponha que você entrou em um grande banco e seu time recebeu a missão de desenhar a arquitetura de um sistema de pagamentos instantâneos, como o PIX. Esse sistema precisa suportar picos de até 10 mil transações por segundo, não pode cair em hipótese alguma, e deve ser capaz de escalar rapidamente em períodos de alta demanda — por exemplo, durante promoções ou datas especiais em que o volume de requisições dispara.

Como você estruturaria uma arquitetura que garanta alta disponibilidade, baixa latência e resiliência diante de falhas ou sobrecargas?


Resposta do dev

Olha, a arquitetura que eu desenhei para o PIX foi pensada em três pilares não-negociáveis: nunca perder uma transação, manter latência abaixo de 200ms e escalar horizontalmente.

Eu organizei em quatro camadas:

Borda

A porta de entrada não deixa a requisição bater direto no core. Na frente, um load balancer distribui o tráfego. Essa camada cuida de autenticação, validação de contrato e proteção contra sobrecarga: rate limit por cliente e por API, além de throttling quando o sistema já está no limite. Também gera uma chave de idempotência para cada requisição — se o cliente mandar o mesmo PIX duas vezes, eu processo só uma.

Fila

Depois da validação, eu não processo na hora. Eu jogo para uma fila FIFO, com ordem garantida e exatamente-uma-vez. Se o banco ou o processador cair, a transação não se perde. Se a fila crescer demais, aplico backpressure: a borda reduz o aceite de novas requisições em vez de derrubar o core. E ainda tenho uma DLQ para isolar falhas sem travar o fluxo principal.

Core

Os workers são stateless e rodam em três zonas de disponibilidade diferentes. Se uma zona cair, as outras assumem. Eles consomem da fila e fazem validação de saldo com transação atômica. Para alta performance uso um banco NoSQL de chave-valor, particionado por ID do usuário para evitar hot partition. Já para extrato e auditoria, que precisam de consistência relacional, uso um banco relacional separado. Timeouts curtos em toda chamada externa evitam worker preso esperando para sempre.

Observabilidade

Cada request gera um correlation ID de ponta a ponta. Implemento retry com backoff exponencial e jitter, além de circuit breaker: se o serviço de saldo estiver instável, eu paro de chamar e devolvo erro rápido, evitando efeito cascata. Toda transação gera um evento imutável que vai para armazenamento de longo prazo, garantindo auditoria de cinco anos.

Escalabilidade

Sobre escalabilidade, eu nunca escalo verticalmente. Escalo horizontalmente: a borda cresce conforme número de requisições, os workers conforme tamanho da fila, e o banco de saldo conforme throughput. Isso me permite sair de 1k para 10k TPS sem mudar arquitetura, apenas adicionando instâncias.

No fim, o que eu garanto é simples: nenhuma transação perdida, nenhuma duplicada, o sistema se protege de sobrecarga com rate limit e, se qualquer parte quebrar, se recupera sozinho.


Mais explicações

Como construir um sistema que nunca cai

Quando falamos de sistemas financeiros, como o PIX, estamos lidando com algo delicado: dinheiro em movimento. E dinheiro não pode simplesmente “sumir” por causa de uma falha técnica. Por isso, arquiteturas de alta performance precisam garantir três coisas:

  • Nenhuma transação perdida.
  • Latência mínima (respostas rápidas).
  • Escalabilidade horizontal (crescer adicionando mais máquinas, não apenas máquinas maiores).

Para atingir esses objetivos, podemos pensar em quatro grandes camadas: Borda, Fila, Core e Observabilidade. Vamos explorar cada uma delas com analogias do dia a dia.

1. Borda — o porteiro da festa

Imagine que você está organizando uma festa. Você não deixa qualquer pessoa entrar direto no salão. Primeiro, há um porteiro que confere o convite, verifica se o nome está na lista e controla a entrada para não lotar. Na arquitetura, essa é a camada de borda.

  • Há um load balancer distribuindo quem entra pelos porteiros disponíveis.
  • Ela faz autenticação (confere se o usuário tem permissão).
  • Faz validação de contrato (checa se a requisição está no formato certo).
  • Aplica rate limit (cada cliente e cada API têm um teto de requisições por segundo — quem passa disso espera ou recebe “não agora”).
  • Aplica throttling quando a casa já está lotada, protegendo o salão inteiro.
  • Gera uma chave de idempotência (como um carimbo único no convite). Assim, se o cliente tentar entrar duas vezes, só a primeira é aceita.

2. Fila — a fila do supermercado

Depois que o porteiro deixa você entrar, você não é atendido imediatamente. Vai para uma fila organizada: quem chegou primeiro, sai primeiro. Na arquitetura, essa é a fila FIFO.

  • Se o caixa (o banco ou processador) cair, os clientes continuam esperando na fila, sem perder a vez.
  • Se a fila ficar longa demais, entra o backpressure: o porteiro reduz a entrada em vez de lotar o salão.
  • Existe também a DLQ (Dead Letter Queue), que é como uma fila separada para clientes com problemas no pagamento. Eles não travam o caixa principal, mas ficam isolados para análise.

3. Core — os caixas do supermercado

Agora chegamos ao núcleo: os workers. Eles são como caixas de supermercado.

  • Stateless: cada caixa não guarda memória dos clientes anteriores. Isso permite abrir ou fechar caixas sem bagunça.
  • Alta disponibilidade: se um caixa quebrar, outros assumem.
  • Timeouts: se uma consulta demora demais, o caixa não fica parado — libera a vez e tenta de forma controlada.
  • Banco NoSQL: funciona como um sistema rápido para conferir saldo em tempo real, particionado por cliente para evitar filas gigantes em um único caixa.
  • Banco relacional: usado para o extrato e auditoria, onde é preciso consistência absoluta, como o registro oficial das compras.

4. Observabilidade — o olho que tudo vê

Nenhum supermercado funciona sem câmeras e supervisores. É preciso acompanhar tudo para evitar problemas. Na arquitetura, isso é a observabilidade.

  • Correlation ID: cada cliente recebe um número único que permite rastrear sua jornada do início ao fim.
  • Retry com backoff exponencial e jitter: se um caixa falhar, o sistema tenta novamente, mas com intervalos cada vez maiores e aleatórios, para não sobrecarregar.
  • Circuit breaker: como um disjuntor elétrico. Se um caixa está dando choque, você desliga rápido para não derrubar toda a rede.
  • Eventos imutáveis: cada transação gera um registro permanente, como uma câmera que grava tudo para auditoria futura.

Escalabilidade — abrindo mais caixas

O segredo não é comprar um caixa maior, mas abrir mais caixas.

  • A borda escala conforme o número de clientes entrando.
  • Os workers escalam conforme o tamanho da fila.
  • O banco de saldo escala conforme o volume de transações.

Assim, o sistema pode crescer de 1.000 para 10.000 transações por segundo apenas adicionando instâncias, sem mudar a arquitetura.

Conclusão

Essa forma de pensar garante que nenhuma transação seja perdida, nenhuma seja duplicada, que o sistema se proteja de sobrecarga e se recupere sozinho em caso de falha.

Em resumo, construir sistemas de alta performance é como organizar um supermercado ou uma festa: precisa de porteiro, fila organizada, caixas eficientes e câmeras de supervisão. Só assim conseguimos garantir que tudo funcione sem caos, mesmo quando o movimento aumenta.