Die Architektur basiert auf einem Saga-Orchestrierungs-Muster, das durch einen ereignisgesteuerten Backbone entkoppelt ist. An der Eingangsseite validiert ein API-Gateway (Kong oder Envoy) JWT-Tokens und leitet Anfragen an einen Policy Enforcement Point (PEP) weiter, der einen Policy Decision Point (PDP) mit Open Policy Agent (OPA) für Echtzeit-AML- und KYC-Überprüfungen gegen Sanktionslisten abfragt.
Der Kern ist der Cross-Ledger Transaction Coordinator, der als Zustandsmaschine implementiert ist, unter Verwendung von Temporal oder einer benutzerdefinierten Saga-Engine über Apache Kafka. Dieser Koordinator verwaltet die verteilte Transaktion über zwei verschiedene Domänen: den Fiat Ledger Adapter (Integration mit SWIFT, ACH oder SEPA über ISO 20022-Messaging) und den Blockchain Adapter (Unterstützung von EVM-Ketten über Alchemy oder Infura sowie Stellar über die Horizon API).
Für Atomarität ohne 2PC (was auf öffentlichen Blockchains nicht verfügbar ist), verwenden wir das Saga-Muster mit kompensierenden Transaktionen. Der Koordinator führt zunächst die lokale Transaktion "Fiat belasten" aus, danach die lokale Transaktion "Token minten/übertragen". Falls letzteres fehlschlägt, wird ersteres durch eine "Fiat gutschreiben"-Transaktion kompensiert. Die Ereignisquellen sorgen dafür, dass alle Zustandsänderungen in PostgreSQL gespeichert und zur Prüfbarkeit an Kafka veröffentlicht werden.
Das Liquidity-Management nutzt einen geografisch verteilten Cache (Redis Cluster) mit WAL-Backing zu Cassandra für die Konsistenz über Regionen hinweg. gRPC-Verbindungen zwischen Mikrodiensten gewährleisten geringe Latenz, während Prometheus und Grafana die Beobachtbarkeit bieten. Der gesamte Stack läuft auf Kubernetes mit Istio für Dienste-Mesh-Funktionen, um mTLS zwischen den Komponenten sicherzustellen.
Bei CrossBridge Payments standen wir vor einer kritischen Anforderung, eine sofortige Überweisung von einem US-Kunden, der ACH verwendet, an einen deutschen Empfänger, der SEPA-Gutschriften erhält, über eine USDC-Stablecoin-Brücke auf Ethereum und Stellar zu ermöglichen, um die Verzögerungen bei Korrespondenzbanken zu reduzieren. Die wichtigste Herausforderung bestand darin, Atomarität sicherzustellen: Wenn die Blockchain-Transaktion scheiterte, nachdem die ACH-Belastung erfolgreich war, würde der Kunde Geld verlieren, während jedoch die endgültige Bestätigung auf Ethereum 12 Sekunden dauert, während die ACH-Abrechnung T+1 erfolgt, aber die Belastungen sofort sind.
Wir haben drei architektonische Ansätze evaluiert. Die erste Option beinhaltete einen zentralisierten Oracle, der sowohl Fiat als auch Krypto verwahrte und als vertrauenswürdiger Mittelsmann fungierte. Während dies die Koordination vereinfachte und die Latenz auf Millisekunden reduzierte, brachte es ein inakzeptables Kontrahentenrisiko mit sich und erfüllte nicht die regulatorischen Anforderungen für dezentrale Verwahrung in bestimmten Gerichtsbarkeiten.
Die zweite Option schlug Hash Time-Locked Contracts (HTLC) für vertrauenslose atomare Swaps zwischen der Fiat-Bank und der Blockchain vor. Dieser Ansatz stellte sich jedoch als nicht durchführbar heraus, da die traditionellen Bankensysteme keine kryptografischen Bausteine bereitstellen, um Hashes on-chain zu überprüfen, und die Timeout-Mechanismen ein schlechtes Benutzererlebnis schufen, das aktive Kundenbeteiligung erforderte.
Letztendlich wählten wir die Saga-Orchestrierung mit Ereignisquellen unter Verwendung von Apache Kafka und Temporal. Dieser Ansatz behandelte die Fiat-Belastung und das Minten von Krypto als separate lokale Transaktionen innerhalb einer Saga. Der Orchestrator sperrte zunächst die Mittel in einem Haupttreuhandkonto über den ACH-Adapter und initiierte dann die USDC-Übertragung auf Stellar (ausgewählt aufgrund der 5-sekündigen Finalität). Wenn der Krypto-Schritt fehlerhaft war, wurde eine kompensierende Transaktion ausgelöst, um die ACH-Sperrung zurückzunehmen.
Das Ergebnis war eine Erfolgsquote von 99,95 % mit einer durchschnittlichen UI-Bestätigungszeit von 800 ms, vollständigen regulatorischen Prüfpfaden, die in PostgreSQL gespeichert wurden, und null Verlusten von Kundengeldern aufgrund von Atomaritätsfehlern während der sechsmonatigen Pilotphase.
Wie reconciliert man die synchrone Natur der REST-API-Kundenerwartungen mit der asynchronen, probabilistischen Endgültigkeit von öffentlichen Blockchain-Netzwerken, ohne HTTP-Verbindungen für Minuten offen zu halten?
Viele Kandidaten schlagen Long-Polling oder blockierende HTTP-Anfragen vor, bis die Blockchain-Bestätigung erfolgt. Dies erschöpft die Server-Threads und löst Gateway-Timeouts aus. Der richtige Ansatz beinhaltet das CQRS-Muster in Kombination mit Ereignisquellen. Die anfängliche Abrechnungsanfrage wird sofort mit einem 202 Accepted-Status und einer eindeutigen Transaktionskorrelations-ID zurückgegeben. Der Kunde abonniert einen WebSocket- oder Server-Sent Events (SSE)-Endpunkt oder fragt einen leichten Status-Endpunkt ab, der von Redis unterstützt wird. Das Backend verarbeitet die Blockchain-Bestätigung asynchron über Kafka-Konsumenten. Sobald die Saga einen terminalen Zustand (abgeschlossen oder kompensiert) erreicht, wird der Status an den Kunden übermittelt.
Welche Strategie gewährleistet die genau-einmalige Ausführung von Fiat-Belastungen, wenn die nachgelagerte Bank-API (JPMorgan Access oder Stripe Treasury) einen Timeout zurückgibt, wodurch Unklarheit darüber entsteht, ob die Gelder tatsächlich überwiesen wurden?
Kandidaten nehmen oft fälschlicherweise an, dass Wiederholungen sicher sind oder dass Idempotenzschlüssel alleine ausreichen. Die robuste Lösung implementiert ein Idempotenz-Ledger mit PostgreSQL und einer PENDING-Zustandsmaschine. Bevor der externe API-Aufruf erfolgt, schreibt der Dienst einen Absichtseintrag mit einem deterministischen Schlüssel (SHA-256 der Transaktions-ID + Zeitstempel-Bucket). Wenn die API timet, fragt ein Hintergrund-Saga-Arbeiter den Idempotenzabfrage-Endpunkt der Bank ab (oder verwendet die Webhook-Abstimmung). Nur bei expliziter Bestätigung oder Ablehnung wird der Zustand auf SUCCESS oder FAILED übertragen.
Wie verhindern Sie Liquiditätsfragmentierung und Doppelbuchungen im gemeinsamen Liquiditätspool, wenn hochfrequente Arbitrage-Bots gleichzeitig über die REST-API und eingehende Blockchain-Ereignisse auf dieselben USDC-Reserven zugreifen?
Dies erfordert optimistisches Locking auf Datenbankebene und verteiltes Locking für kritische Abschnitte. Der Liquiditätsdienst führt versionierte Zeilen in PostgreSQL; jede Aktualisierung erhöht die Version. Wenn ein Abhebungsversuch unternommen wird, überprüft das System die Version. Wenn ein paralleles Blockchain-Ereignis die Zeile geändert hat (Versionskonflikt), wird die Transaktion wiederholt. Für den schnellsten Pfad wird ein Redis Redlock erworben, bevor die Salden überprüft werden, um sequentiellen Zugriff sicherzustellen. Darüber hinaus überwacht ein Circuit Breaker (Resilience4j) das Verhältnis der Kontention im Liquiditätspool.