Durable Execution vs. Saga Pattern für Zahlungs-Workflows
Saga-Kompensationen sind notwendig, aber nicht ausreichend. Durable Execution bietet die Exactly-Once-Garantien, die Finanzprozesse erfordern.
Durable Execution vs. Saga Pattern: Das richtige Workflow-Modell für Zahlungen
Schritt 3 von 5 schlägt fehl. Der Queue-Consumer crasht. Beim Neustart: Replay ab Schritt 1? Sprung zu Schritt 4? Die Antwort hängt von Zustand ab, den die Queue nicht verfolgt.
Das ist das zentrale Problem mehrstufiger Finanzprozesse. Kontoeröffnung erfordert vier koordinierte Schritte: Entität erstellen, Ledger-Konten provisionieren, IBAN zuweisen, KYC-Verifikation auslösen. Zahlungsausführung erfordert fünf: validieren, screenen, belasten, an Clearing übermitteln, Settlement verfolgen. Jeder Schritt hängt vom vorherigen ab. Jeder Schritt hat Seiteneffekte, die nicht leichtfertig wiederholt werden können.
Zwei architektonische Muster adressieren dieses Problem. Sie lösen es unterschiedlich, mit unterschiedlichen Trade-offs, und die Wahl ist wichtiger als die meisten Architekturentscheidungen in einem Zahlungssystem.
Das Saga-Pattern
Sagas koordinieren unabhängige Services durch kompensierende Transaktionen. Zwei Varianten existieren.
Choreografie: Jeder Service publiziert Events. Der nächste Service abonniert und handelt. Wenn etwas fehlschlägt, publiziert der fehlerhafte Service ein Kompensations-Event, und vorgelagerte Services hören zu und machen ihre Arbeit rückgängig.
Der Reiz ist Entkopplung. Kein zentraler Koordinator. Jeder Service besitzt seine Logik. Einen neuen Schritt hinzufügen durch Hinzufügen eines neuen Subscribers.
Das Problem ist Sichtbarkeit. Der „Prozess" existiert nirgends als einzelnes Artefakt. Er ist eine emergente Eigenschaft von Event-Flows über Services hinweg. Das Debugging einer fehlgeschlagenen Zahlung erfordert die Korrelation von Logs über jeden beteiligten Consumer. Wenn ein Event verloren ging (und Events gehen verloren, Netzwerkpartitionen, Consumer-Crashes vor dem Acknowledgment, Dead-Letter-Overflow), ist der Fehler still. Keine Komponente weiß, dass der Prozess unvollständig ist, weil keine Komponente den Prozess verfolgt.
Orchestrierung: Ein zentraler Koordinator sendet Befehle nacheinander an jeden Service. Der Koordinator kennt den aktuellen Schritt. Wenn ein Schritt fehlschlägt, führt der Koordinator Kompensation in umgekehrter Reihenfolge aus.
Das ist besser. Der Prozess ist an einer Stelle sichtbar. Ein Operator kann den Zustand des Koordinators inspizieren und sehen: Schritt 3 von 5 ist ausstehend. Der Koordinator ist die Single Source of Truth für den Prozess.
Aber: Der Koordinator selbst muss Ausfälle überleben. Wenn der Koordinator zwischen Schritt 3 (Konto belasten) und Schritt 4 (an Clearing übermitteln) crasht, was passiert? Die Antwort hängt davon ab, wie der Koordinator seinen eigenen Zustand persistiert. Wenn er eine In-Memory-State-Machine verwendet, ist der Zustand verloren. Wenn er in eine Datenbank persistiert, hängt die Wiederherstellung davon ab, ob der Datenbank-Write vor dem Crash committed hat. Die eigene Zuverlässigkeit des Koordinators wird zum Design-Problem, eines, das Saga-Orchestrierung nicht inhärent löst.
Beide Saga-Varianten teilen eine fundamentale Eigenschaft: Jeder Schritt ist eine unabhängige Transaktion. Die Saga koordiniert sie. Aber die Koordination selbst ist nicht transaktional. Die Lücke zwischen „Schritt 3 hat committed" und „der Koordinator hat aufgezeichnet, dass Schritt 3 committed hat" ist der Ort, an dem Datenverlust sich versteckt.
Durable Execution
Durable Execution wählt einen anderen Ansatz. Die Workflow-Engine journalisiert jeden Schritt VOR der Ausführung. Das Journal ist der Prozesszustand. Wenn die Engine crasht und neu startet, spielt sie das Journal ab und nimmt am exakten Unterbrechungspunkt wieder auf.
Das mentale Modell unterscheidet sich von Sagas. In einer Saga definieren Sie den Vorwärtspfad und den Kompensationspfad als separate Anliegen. In Durable Execution schreiben Sie den Workflow als lineare Funktion, Schritt 1, Schritt 2, Schritt 3, und die Engine garantiert, dass die Funktion abgeschlossen wird. Wenn ein Schritt permanent fehlschlägt (kein transienter Fehler, sondern ein echter Business-Fehler, „Konto existiert nicht"), führt die Engine die Kompensation als Teil desselben journalisierten Workflows aus.
Drei Eigenschaften unterscheiden Durable Execution von Saga-Orchestrierung:
Das Journal überlebt Prozess-Neustarts. Die Engine schreibt jeden Schritt in ein dauerhaftes Log vor der Ausführung. Beim Neustart spielt sie das Log ab und nimmt wieder auf. Das Journal ist keine Optimierung und kein Nachgedanke, es ist der Ausführungsmechanismus. Der Prozess läuft nicht „auf" dem Journal. Der Prozess IST das Journal, abgespielt.
Idempotenz wird von der Engine garantiert. In einer Saga muss jeder Service Idempotenz unabhängig implementieren. Wenn der Koordinator Schritt 3 wiederholt, muss der Service das Duplikat erkennen und das vorherige Ergebnis zurückgeben. In Durable Execution verfolgt die Engine, welche Schritte abgeschlossen sind. Beim Replay geben abgeschlossene Schritte ihre gecachten Ergebnisse zurück, ohne erneut auszuführen. Der Service muss nicht idempotent sein, die Engine stellt sicher, dass er höchstens einmal pro Workflow-Instanz aufgerufen wird.
Das Journal ist der Audit-Trail. Jeder Workflow hat eine Correlation ID. Jeder Schritt wird mit Inputs, Outputs, Dauer und Ergebnis aufgezeichnet. Ein Auditor kann den vollständigen Lebenszyklus einer Zahlung anhand einer einzigen Kennung rekonstruieren. Kein Logging-Feature, eine strukturelle Eigenschaft des Ausführungsmodells. Der Audit-Trail existiert, weil das Journal existiert, und das Journal existiert, weil die Engine ohne es nicht funktionieren kann.
Ein konkretes Beispiel: SEPA-Überweisung
Durchlauf einer Zahlung mit beiden Mustern.
Der Happy Path (beide Muster behandeln dies identisch):
- IBAN und Betrag validieren ✓
- AML-Screening (externer Provider) ✓
- Sender-Konto belasten (Ledger) ✓
- An Clearing übermitteln (SEPA SCT via CSM) ✓
- Settlement-Status verfolgen ✓
Der Fehlerfall: Schritt 4 wird vom Clearing-Netzwerk abgelehnt.
Das Konto des Senders wurde belastet (Schritt 3). Das Clearing-Netzwerk hat die Übermittlung abgelehnt (Schritt 4). Die Belastung muss rückgängig gemacht werden.
Saga-Ansatz:
Der Clearing-Adapter publiziert ein PaymentRejected-Event. Ein Kompensations-Consumer nimmt es auf, ruft das Ledger auf, um die Belastung rückgängig zu machen, und publiziert DebitReversed. Der ursprüngliche Zahlungsdatensatz wird auf FAILED aktualisiert.
Aber: Was, wenn der Kompensations-Consumer crasht, bevor er die Belastung rückgängig macht? Das PaymentRejected-Event sitzt in der Dead-Letter-Queue. Das Konto des Senders bleibt belastet. Keine Komponente verfolgt diesen Zustand aktiv. Die Entdeckung hängt entweder von einem Reconciliation-Lauf (Stunden oder Tage später) oder einer Kundenbeschwerde ab.
Mitigation existiert: Persistente Queues mit At-Least-Once-Delivery, Consumer-Health-Monitoring, Dead-Letter-Alerting. Jede Mitigation ist ein zusätzliches System zum Bauen und Warten. Der Kompensationspfad wird so komplex wie der Vorwärtspfad.
Durable-Execution-Ansatz:
Schritt 4 schlägt fehl. Die Engine zeichnet den Fehler im Journal auf. Sie führt den Kompensations-Handler (Belastung rückgängig machen) als nächsten journalisierten Schritt aus. Wenn die Engine während der Stornierung crasht, spielt sie das Journal beim Neustart ab und führt die Stornierung erneut aus (die idempotent ist, weil die Engine den Schrittzustand gecacht hat).
Die vollständige Sequenz, Vorwärtspfad, Fehler, Kompensation, ist in einem Journal mit einer Correlation ID. Ein Operator inspiziert den Workflow und sieht:
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
Keine forensische Log-Analyse. Keine Dead-Letter-Queue zum Überwachen. Keine Reconciliation erforderlich, um den Fehler zu entdecken. Der Prozess ist selbstdokumentierend.
Wo jedes Muster passt
| Aspekt | Saga (Choreografie) | Saga (Orchestrierung) | Durable Execution |
|---|---|---|---|
| Prozess-Sichtbarkeit | Über Event-Logs verteilt | Zentraler Koordinator | Einzelnes Journal mit vollem Replay |
| Wiederherstellungsmodell | Kompensations-Events (können verloren gehen) | Koordinator nimmt wieder auf (wenn Zustand persistiert) | Journal-Replay (garantiert) |
| Audit-Trail | Erfordert Log-Aggregation über Services | Koordinator-Log (Single Point) | Eingebaut, Journal IST der Trail |
| Idempotenz | Jeder Service muss implementieren | Jeder Service muss implementieren | Engine-garantiert |
| Teilausfall | Still, wenn Kompensations-Event verloren | Unsicher, wenn Koordinator mid-step crasht | Journal überlebt, Replay nimmt wieder auf |
| Komplexität | Niedrig (pro Service), hoch (systemweit) | Mittel (Koordinator), mittel (Services) | Niedrig (Workflow-Code), niedrig (Infrastruktur) |
| Am besten für | Lose gekoppelte, Low-Stakes-Koordination | Multi-Service-Orchestrierung | Finanzprozesse mit Exactly-Once-Anforderung |
Sagas sind nicht falsch. Sie funktionieren gut für Koordination, die Eventual Consistency tolerieren kann: Bestandsreservierungen, Benachrichtigungs-Workflows, Analytics-Pipelines. Die Choreografie-Variante glänzt, wenn Services wirklich unabhängig sind und der „Prozess" eine Annehmlichkeit ist, keine Anforderung.
Für Finanzprozesse, wo jeder Schritt irreversible Seiteneffekte hat, wo Kompensation beweisbar sein muss, wo ein Auditor fragen wird „zeigen Sie mir jeden Schritt dieser Zahlung", bietet Durable Execution stärkere Garantien bei geringerer operativer Komplexität.
Die Branche hat konvergiert
Die Evidenz ist praktisch, nicht theoretisch. Die Zahlungsindustrie hat ihre Wahl getroffen:
- Stripe verwendet Temporal (Durable Execution) für Zahlungsorchestration.
- Revolut verwendet Temporal für kritische Zahlungsflows.
- Wise migrierte von Saga-Orchestrierung Richtung Temporal.
- N26 verwendet Kafka + Sagas, und diskutiert öffentlich die operative Komplexität des Kompensationsmanagements.
Das Muster ist klar. Für zahlungskritische Pfade konvergiert die Branche auf Durable Execution. Das journal-basierte Modell liefert die Rückverfolgbarkeit, die Regulierer fordern (DORA Art. 11-12), und die operative Sichtbarkeit, die Engineering-Teams brauchen.
Weiterlesen: Workflows, Durable Execution Engine | Payments, Zahlungsorchestration
Quellen:
- Garcia-Molina, Hector und Salem, Kenneth. „Sagas." SIGMOD '87, das originale Saga-Pattern-Paper
- DORA, Verordnung (EU) 2022/2554, Art. 11-12 (IKT-Rückverfolgbarkeit und Wiederherstellung)
- Restate Dokumentation: „Microservice Orchestration" (https://docs.restate.dev/tour/microservice-orchestration)
- Temporal Dokumentation: „What is durable execution?" (https://docs.temporal.io/concepts)