Quando as gravações síncronas se tornam o gargalo
Um cliente envia uma transação. O Midaz deve fazer duas coisas: validá-la e persistir o resultado. No modo síncrono, as duas etapas rodam na mesma requisição. Esse modelo é simples e previsível, mas tem um teto. Em alto volume, as gravações no banco de dados se tornam o gargalo. Cada transação ocupa uma conexão, espera por locks e disputa I/O. O modo assíncrono rompe essa dependência. O Midaz valida a transação, retorna a resposta de imediato e persiste os dados em segundo plano através do RabbitMQ. O cliente recebe respostas mais rápidas. Para orientações mais amplas de escalabilidade, veja Estratégias de escalabilidade.
Como funciona
Modo síncrono (padrão)
Figura 1. Fluxo de transação síncrono.
-
O cliente envia um
POST /transactionpara a API do Midaz. - A API valida a requisição. Ela executa aqui a validação do formato da requisição, as checagens de saldo e a aplicação de limites.
- A API grava no PostgreSQL. Ela persiste a transação e as operações dela no mesmo ciclo de requisição.
-
A API retorna
201 Createdao cliente com a transação criada. A resposta carrega o statusCREATED, e o Midaz armazena a transação comoAPPROVED. Um201significa que o Midaz aplicou a transação aos saldos.
- O tempo de resposta inclui a latência de gravação no banco de dados.
- Cada transação é uma operação independente no banco de dados.
- Mais simples de entender.
Mesmo no modo síncrono, o Midaz atualiza os saldos de forma atômica no Redis durante a requisição. O Redis é a fonte de verdade para saldos. A gravação acima persiste a transação e as operações dela, não as linhas de saldo do Postgres. O worker de sincronização de saldo, que roda continuamente, reconcilia essas linhas (veja Sincronização de saldo).
Modo assíncrono
O Midaz valida a transação da mesma forma. Em vez de uma gravação direta no banco de dados, o Midaz publica uma mensagem no RabbitMQ. Um consumidor em segundo plano pega a mensagem e trata a persistência separadamente.Figura 2. Fluxo de transação assíncrono. O cliente recebe uma resposta assim que a mensagem é publicada, e a persistência acontece em segundo plano.
-
O cliente envia um
POST /transactionpara a API do Midaz. - A API valida a requisição. Ela executa a validação do formato da requisição, as checagens de saldo e a aplicação de limites exatamente como no modo síncrono.
- A API publica o payload da transação no RabbitMQ em vez de gravar diretamente no banco de dados.
-
A API retorna
201 Createdao cliente assim que a fila aceita a mensagem. O cliente não espera pela persistência no banco de dados. A resposta carrega o statusCREATED, e o Midaz armazena a transação comoAPPROVED. Um201significa que o Midaz aplicou a transação aos saldos. - O RabbitMQ entrega a mensagem a um consumidor em segundo plano, desacoplado da requisição da API.
- O consumidor grava no PostgreSQL. Ele persiste a transação e as operações dela a partir da mensagem enfileirada. O worker de sincronização de saldo copia os saldos para o PostgreSQL em ambos os modos (veja a seção Sincronização de saldo).
- O tempo de resposta exclui a latência de gravação no banco de dados.
- As consultas de lista mostram uma transação nova depois que o consumidor a grava.
- Os consumidores em segundo plano gravam no banco de dados no próprio ritmo, com novas tentativas. As inserções em lote exigem o Bulk Recorder habilitado.
Resiliência embutida
Se a publicação no RabbitMQ falhar no modo assíncrono, o Midaz grava a transação no banco de dados durante a requisição. Se essa gravação também falhar, a transação continua aplicada aos saldos. O Midaz mantém o registro da transação e tenta a gravação de novo em segundo plano. O modo síncrono usa a mesma recuperação quando a gravação dele no banco de dados falha. Isso significa:
- Durante uma indisponibilidade da fila, o Midaz grava diretamente no banco de dados.
- Uma gravação com falha no banco de dados não rejeita uma transação que o Midaz já aplicou aos saldos.
- O Midaz registra em log a falha da fila e a gravação adiada, para que a sua equipe de operações possa investigá-las.
Habilitando o modo assíncrono
Defina uma variável de ambiente na aplicação do ledger:
false (o padrão), todas as transações usam o processamento síncrono e persistem diretamente no PostgreSQL. O ledger ainda se conecta ao RabbitMQ e roda o consumidor dele nesse modo.
Com true, o ledger publica os payloads de transação no exchange do RabbitMQ configurado. Um consumidor em segundo plano então trata a persistência.
Configuração do RabbitMQ
O modo assíncrono usa as seguintes configurações do RabbitMQ (todas no
.env do ledger):
Sincronização de saldo
Um worker dedicado de sincronização de saldo copia os saldos do Redis para o PostgreSQL. Esse worker roda tanto no modo síncrono quanto no assíncrono.
O worker de sincronização de saldo roda automaticamente nos dois modos. Você não precisa de nenhuma configuração extra além de uma instância do Redis disponível.
Circuit breaker do RabbitMQ
Um circuit breaker embutido protege as publicações no RabbitMQ de mensagens de auditoria e eventos de overdraft. Ele monitora a saúde da conexão com o RabbitMQ e falha rápido quando o broker cai. Isso evita acúmulo de requisições e falhas em cascata.
Configuração do circuit breaker
Como o modo assíncrono se conecta ao Bulk Recorder
O modo assíncrono e o Bulk Recorder trabalham juntos:
- O modo assíncrono desacopla a resposta da API da persistência. As transações vão para o RabbitMQ em vez de diretamente para o PostgreSQL.
- O Bulk Recorder otimiza como o consumidor grava essas mensagens no banco de dados. Ele agrupa várias mensagens em inserções em lote únicas.
Quando usar o modo assíncrono
Use o modo assíncrono quando:
- Você precisa de tempos de resposta mais baixos da API para a criação de transações.
- Sua carga de trabalho envolve altos volumes de transações (centenas ou mais por segundo).
- Você executa operações em lote, como repasses em massa ou liquidações.
- Você quer desacoplar a camada de API do desempenho do banco de dados.
- Você precisa de persistência de transação direta e vinculada à requisição.
- O volume de transações é baixo a moderado.
- Você trabalha em um ambiente de desenvolvimento ou teste, onde a simplicidade importa mais que o throughput.

