Execução durável vs. padrão Saga para fluxos de pagamento
Compensações Saga são necessárias mas insuficientes. Execução durável fornece garantias exactly-once que processos financeiros exigem.
Execução Durável vs. Padrão Saga: Escolhendo o Modelo de Workflow Correto para Pagamentos
O passo 3 de 5 falha. O consumer da fila cai. Ao reiniciar, ele reproduz do passo 1? Pula para o passo 4? A resposta depende de estado que a fila não rastreia.
Este é o problema central dos processos financeiros multi-passo. A abertura de conta requer quatro passos coordenados: criar entidade, provisionar contas de ledger, atribuir IBAN, acionar verificação KYC. A execução de pagamento requer cinco: validar, screenar, debitar, enviar ao clearing, rastrear settlement. Cada passo depende do anterior. Cada passo tem efeitos colaterais que não podem ser repetidos casualmente.
Dois padrões arquitetônicos abordam este problema. Eles o resolvem de forma diferente, com trade-offs diferentes, e a escolha importa mais do que a maioria das decisões de arquitetura em um sistema de pagamentos.
O Padrão Saga
Sagas coordenam serviços independentes através de transações compensatórias. Existem duas variantes.
Coreografia: cada serviço publica eventos. O próximo serviço se inscreve e age. Quando algo falha, o serviço que falhou publica um evento de compensação, e os serviços upstream escutam e desfazem seu trabalho.
O atrativo é o desacoplamento. Sem coordenador central. Cada serviço é dono de sua lógica. Adicionar um novo passo é adicionar um novo subscriber.
O problema é a visibilidade. O "processo" não existe em lugar nenhum como artefato único. É uma propriedade emergente de fluxos de eventos entre serviços. Debugar um pagamento falho requer correlacionar logs através de cada consumer que participou. Se um evento foi perdido (e eventos se perdem, partições de rede, crashes de consumer antes do acknowledgment, overflow de dead-letter), a falha é silenciosa. Nenhum componente sabe que o processo está incompleto, porque nenhum componente rastreia o processo.
Orquestração: um coordenador central envia comandos a cada serviço em sequência. O coordenador conhece o passo atual. Se um passo falha, o coordenador executa compensação em ordem reversa.
Isso é melhor. O processo é visível em um lugar. Um operador pode inspecionar o estado do coordenador e ver: passo 3 de 5 está pendente. O coordenador é a fonte única de verdade para o processo.
Mas: o próprio coordenador deve sobreviver a falhas. Se o coordenador cai entre o passo 3 (debitar a conta) e o passo 4 (enviar ao clearing), o que acontece? A resposta depende de como o coordenador persiste seu próprio estado. Se usa uma máquina de estados em memória, o estado é perdido. Se persiste em banco de dados, a recuperação depende de se a escrita no banco commitou antes do crash. A própria confiabilidade do coordenador se torna um problema de design, um que a orquestração Saga não resolve inerentemente.
Ambas as variantes Saga compartilham uma propriedade fundamental: cada passo é uma transação independente. A saga as coordena. Mas a coordenação em si não é transacional. A lacuna entre "passo 3 commitou" e "o coordenador registrou que passo 3 commitou" é onde a perda de dados se esconde.
Execução Durável
A execução durável toma uma abordagem diferente. O motor de workflows journaliza cada passo ANTES de executá-lo. O journal é o estado do processo. Se o motor cai e reinicia, reproduz o journal e retoma no ponto exato de interrupção.
O modelo mental é diferente das Sagas. Em uma Saga, você define o caminho forward e o caminho de compensação como preocupações separadas. Na execução durável, você escreve o workflow como uma função linear, passo 1, passo 2, passo 3, e o motor garante que a função se complete. Se um passo falha permanentemente (não um erro transitório, mas uma falha de negócio genuína, "a conta não existe"), o motor executa a compensação como parte do mesmo workflow journalizado.
Três propriedades distinguem a execução durável da orquestração Saga:
O journal sobrevive reinícios de processo. O motor escreve cada passo em um log durável antes da execução. Ao reiniciar, reproduz o log e retoma. O journal não é uma otimização nem um pensamento posterior, é o mecanismo de execução. O processo não roda "em cima do" journal. O processo É o journal, reproduzido.
A idempotência é garantida pelo motor. Em uma Saga, cada serviço deve implementar idempotência independentemente. Se o coordenador retenta o passo 3, o serviço deve detectar o duplicado e retornar o resultado anterior. Na execução durável, o motor rastreia quais passos foram completados. Ao reproduzir, passos completados retornam seus resultados cacheados sem re-executar. O serviço não precisa ser idempotente, o motor garante que seja chamado no máximo uma vez por instância de workflow.
O journal é a trilha de auditoria. Cada workflow tem um ID de correlação. Cada passo é registrado com entradas, saídas, duração e resultado. Um auditor pode reconstruir o ciclo de vida completo de um pagamento a partir de um único identificador. Não é uma funcionalidade de logging, é uma propriedade estrutural do modelo de execução. A trilha de auditoria existe porque o journal existe, e o journal existe porque o motor não pode funcionar sem ele.
Um Exemplo Concreto: Transferência SEPA
Percorra um pagamento com ambos os padrões.
O caminho feliz (ambos os padrões o tratam identicamente):
- Validar IBAN e valor ✓
- Screening AML (provedor externo) ✓
- Debitar conta do remetente (ledger) ✓
- Enviar ao clearing (SEPA SCT via CSM) ✓
- Rastrear status de settlement ✓
A falha: passo 4 é rejeitado pela rede de clearing.
A conta do remetente foi debitada (passo 3). A rede de clearing rejeitou o envio (passo 4). O débito deve ser revertido.
Abordagem Saga:
O adaptador de clearing publica um evento PaymentRejected. Um consumer de compensação o pega, chama o ledger para reverter o débito, e publica DebitReversed. O registro do pagamento original é atualizado para FAILED.
Mas: e se o consumer de compensação cair antes de reverter o débito? O evento PaymentRejected fica na dead-letter queue. A conta do remetente permanece debitada. Nenhum componente rastreia ativamente este estado. A descoberta depende de uma execução de reconciliação (horas ou dias depois) ou uma reclamação do cliente.
Abordagem de execução durável:
O passo 4 falha. O motor registra a falha no journal. Executa o handler de compensação (reverter o débito) como o próximo passo journalizado. Se o motor cai durante a reversão, reproduz o journal ao reiniciar e re-executa a reversão (que é idempotente porque o motor cacheou o estado do passo).
A sequência completa, caminho forward, falha, compensação, está em um journal com um ID de correlação. Um operador inspeciona o workflow e vê:
Workflow: SEPA-CT-2026-02-21-00847
Step 1: Validate → OK (12ms)
Step 2: AML Screen → OK (340ms, provider: screening-svc)
Step 3: Debit → OK (0.4ms, transfer_id: 9a3f...)
Step 4: Submit Clearing → REJECTED (reason: AC03, invalid creditor account)
Step 5: Compensate Debit → OK (0.3ms, reversal_id: b7c1...)
Status: COMPENSATED
Sem análise forense de logs. Sem dead-letter queue para monitorar. Sem reconciliação necessária para descobrir a falha. O processo é auto-documentante.
Onde Cada Padrão Se Encaixa
| Aspecto | Saga (Coreografia) | Saga (Orquestração) | Execução Durável |
|---|---|---|---|
| Visibilidade do processo | Distribuída entre logs de eventos | Coordenador central | Journal único com replay completo |
| Modelo de recuperação | Eventos de compensação (podem se perder) | Coordenador retoma (se estado persistido) | Replay de journal (garantido) |
| Trilha de auditoria | Requer agregação de logs entre serviços | Log do coordenador (ponto único) | Integrada, o journal É a trilha |
| Idempotência | Cada serviço deve implementar | Cada serviço deve implementar | Garantida pelo motor |
| Falha parcial | Silenciosa se evento de compensação se perde | Incerta se coordenador cai mid-step | Journal sobrevive, replay retoma |
| Complexidade | Baixa (por serviço), alta (sistema) | Média (coordenador), média (serviços) | Baixa (código de workflow), baixa (infraestrutura) |
| Melhor para | Coordenação loosely coupled, low-stakes | Orquestração multi-serviço | Processos financeiros com requisito exactly-once |
Sagas não estão erradas. Funcionam bem para coordenação que pode tolerar consistência eventual: reservas de inventário, workflows de notificação, pipelines de analytics. A variante de coreografia se destaca quando os serviços são verdadeiramente independentes e o "processo" é uma conveniência, não um requisito.
Para processos financeiros, onde cada passo tem efeitos colaterais irreversíveis, onde a compensação deve ser demonstrável, onde um auditor vai perguntar "mostre-me cada passo deste pagamento", a execução durável fornece garantias mais fortes com menos complexidade operacional.
A Indústria Convergiu
A evidência é prática, não teórica. A indústria de pagamentos tomou sua decisão:
- Stripe usa Temporal (execução durável) para orquestração de pagamentos.
- Revolut usa Temporal para fluxos de pagamento críticos.
- Wise migrou de orquestração Saga para Temporal.
- N26 usa Kafka + Sagas, e discute publicamente a complexidade operacional da gestão de compensação.
O padrão é claro. Para caminhos críticos de pagamento, a indústria está convergindo para execução durável. O modelo baseado em journal fornece a rastreabilidade que reguladores requerem (DORA Art. 11-12) e a visibilidade operacional que equipes de engenharia precisam.
Leia mais: Workflows, Motor de Execução Durável | Payments, Orquestração de Pagamentos
Fontes:
- Garcia-Molina, Hector e Salem, Kenneth. "Sagas." SIGMOD '87, o paper original do padrão Saga
- DORA, Regulamento (UE) 2022/2554, Art. 11-12 (rastreabilidade e recuperação TIC)
- Documentação do Restate: "Microservice Orchestration" (https://docs.restate.dev/tour/microservice-orchestration)
- Documentação do Temporal: "What is durable execution?" (https://docs.temporal.io/concepts)