Playbook

Warum Zahlungssysteme verteilte Systeme sind (Warum Zahlungssysteme Verteilte Systeme Sind)

Eine Zahlung ist nie die Aufgabe eines einzigen Services: Warenkorb, Bestand, Provider-Gateway und Ledger müssen sich einigen. Warum die synchrone Kette bricht.

Verteilte Payment Engine (Distributed Payment Engine)

Teil 1 von 22

Serie zur verteilten Payment-Architektur — die Lücke zwischen Capture und Complete.

Distributed payment engine architecture diagram

Eine Zahlung ist kein Button, sondern Koordination

Wenn ein Checkout-Flow in einer E-Commerce-Plattform „Kunden belasten“ sagt, müssen in Wirklichkeit fünf verschiedene Systeme sich auf dieselbe Tatsache einigen: Ist der Warenkorb eingefroren, ist Bestand verfügbar, hat das Provider-Gateway das Geld erhalten, ist die Bestellung bestätigt, stimmt der Ledger-Eintrag. Nichts davon lebt in einem einzigen Prozess oder einer einzigen Transaktion.

Warenkorb-Service   Bestands-Service   Checkout Orchestrator   Provider-Gateway   Ledger-Service
        |                   |                     |                    |                |
        +-------------------+---------------------+--------------------+----------------+
                            eine Bestellung, fünf getrennte Wahrheiten

Dieser Teil erklärt, warum ein Zahlungsablauf als Problem verteilter Systeme entworfen werden muss — nicht als Funktion eines einzelnen Services.

Begriffe, dort definiert, wo sie zuerst auftauchen

📦 Checkout Orchestrator
Koordiniert die Schritte eines Bestellablaufs (Warenkorb, Zahlung, Bestand, Bestätigung); hält selbst kein Geld und keinen Bestand, nur Entscheidungen und ihre Reihenfolge.

📦 Provider-Gateway
Die Abstraktionsschicht, die einen realen Zahlungsanbieter (PSP) in das interne Domänenmodell übersetzt.

📦 PSP (Payment Service Provider)
Das externe System, das die Karte tatsächlich belastet und das Geld bewegt; es liegt außerhalb Ihrer Transaktionsgrenze.

📦 Verteilte Transaktion
Eine Operation, die mehrere unabhängige Systeme unter einer einzigen Alles-oder-nichts-Garantie umfasst.

📦 Eventual Consistency
Ein Konsistenzmodell, das akzeptiert, dass Systeme sich in Kürze auf dieselbe Wahrheit zubewegen — nicht sofort.

Ein Team, das diese Begriffe nicht trennt, behandelt den PSP wie seine eigene Datenbank. Der PSP tritt Ihrer Transaktion niemals bei; er meldet nur seine eigene Wahrheit, auf seinem eigenen Zeitplan.

Eine Anfrage, fünf erforderliche Bestätigungen

Wenn ein Kunde auf „Bezahlen“ klickt, läuft im Hintergrund eine Reihe von Entscheidungen ab: Ist der Warenkorbpreis eingefroren, ist Bestand reserviert, hat die Anfrage das Provider-Gateway erreicht, hat der PSP das Geld tatsächlich abgebucht, sind die Bestellpositionen finalisiert, ist der Ledger-Eintrag geöffnet. Jede dieser Entscheidungen gehört zu einem anderen Service, mit einer anderen Datenbank im Hintergrund.

Das Problem beginnt genau hier: Verkettet man diese sechs Schritte synchron in einer einzigen HTTP-Aufrufkette, entsteht eine lange, zerbrechliche Sequenz, in der jeder Schritt vom vorherigen abhängt.

Client → Checkout Orchestrator → Warenkorb-Service → Bestands-Service → Provider-Gateway → PSP

Wo die synchrone Kette bricht

Läuft irgendein Schritt in dieser Kette in ein Timeout, bleiben zwei unbeantwortete Fragen: Ist die Anfrage überhaupt angekommen, und wenn ja, wurde sie verarbeitet? Ein Timeout vom PSP bedeutet nicht „das Geld wurde nicht abgebucht“ — es bedeutet „ich habe keine Antwort erhalten“. Die gleiche Anfrage blind zu wiederholen, kann den Kunden zweimal belasten.

Checkout Orchestrator --(Timeout)--> Provider-Gateway --(???)--> PSP
                                                  wurde das Geld abgebucht oder nicht?

Diese Unsicherheit ist kein Bug, den man weg-coden kann; sie ist die natürliche Folge einer synchronen Kette. Netzwerke sind per Definition unzuverlässig — je länger die Kette, desto mehr Unsicherheit sammelt sich an.

Warum „alles oder nichts“ hier nicht funktioniert

Klassische Protokolle für verteilte Transaktionen (wie Two-Phase-Commit) setzen voraus, dass alle Teilnehmer denselben Koordinator, dasselbe Sperrprotokoll und dieselbe Netzwerkzuverlässigkeit teilen. Der PSP ist nicht Teil dieser Welt: Er hält für Sie keine Sperre, er hört nicht auf Ihren Commit-/Rollback-Aufruf, und er teilt Ihnen mit, was passiert ist — nach seinem eigenen Zeitplan, synchron oder, häufiger, per Webhook.

Der Versuch, „Zahlung + Bestand + Bestellung“ in eine einzige Transaktion zu zwängen, löst kein unlösbares Problem — er versteckt es nur. Der Fehlermodus ist nicht verschwunden; er ist nur unsichtbar, bis er in Produktion auftaucht.

Die ereignisbasierte Lösung: zwei Wahrheiten, zwei Zeitachsen

Das Modell, das tatsächlich funktioniert, verkürzt die synchrone Kette und übergibt alles danach an Ereignisse. Sie senden die Anfrage an das Provider-Gateway, Sie erfassen die Antwort des PSP (synchron oder per Webhook) als Ereignis, und jeder nachgelagerte Schritt — Bestand, Ledger, Bestellbestätigung — wird zu einem unabhängigen, idempotenten Konsumenten dieses Ereignisses.

Provider-Gateway → PaymentCaptured (Event) → Outbox
                                              ↓
            Bestands-Service   Ledger-Service   Checkout Orchestrator
            (jeder konsumiert unabhängig, in eigenem Tempo, mit eigenen Retries)

In diesem Modell sind „Zahlung erfolgreich“ und „Bestellung abgeschlossen“ nicht mehr dieselbe augenblickliche Tatsache — es sind zwei zusammenhängende Wahrheiten auf zwei Zeitachsen mit einer messbaren Lücke dazwischen. Systeme, die diese Lücke nicht akzeptieren, geraten direkt in die Zustandsmaschinen-Fehler, die wir im nächsten Teil behandeln.

Die am häufigsten verwechselten Zuordnungen

❌ Ein Zahlungsablauf ist die Funktion eines Services
✓ Ein Zahlungsablauf ist Koordination zwischen mehreren unabhängigen Services

❌ Der PSP verhält sich wie eine Tabelle in unserer eigenen Datenbank
✓ Der PSP ist ein extern beobachtetes System mit eigenem Zeitplan

❌ Timeout bedeutet, die Operation ist fehlgeschlagen
✓ Timeout bedeutet, das Ergebnis ist unbekannt — Retry ohne Idempotenz ist unsicher

❌ Eine verteilte Transaktion kann dieses Problem „lösen“
✓ Verteilte Transaktionen funktionieren an externen Grenzen wie einem PSP praktisch nicht

Diese vier falschen Zuordnungen stecken hinter den meisten „Warum wurde dieser Kunde doppelt belastet“-Incidents.

Checkliste zur Prüfung des eigenen Ablaufs

  1. Zählen Sie, wie viele Services in wie viele getrennte Datenbanken schreiben, wenn Ihr Zahlungsablauf läuft.
  2. Wenn der Aufruf an Ihr Provider-Gateway ein Timeout produziert — wiederholt Ihr Code automatisch, und trägt dieser Retry einen Idempotenzschlüssel?
  3. Wird „Zahlung erfolgreich“ im selben Datensatz wie „Bestellung abgeschlossen“ gespeichert, oder in getrennten Tabellen?
  4. Wenn ein PSP-Webhook sich verzögert oder nie ankommt, wie viele Stunden vergehen, bis Ihr System es merkt?
  5. Welcher Schritt in Ihrer synchronen Kette dauert am längsten, und was passiert mit dem Rest der Kette, wenn dieser Schritt ausfällt?

Wenn Sie diese fünf Fragen nicht klar beantworten können, ist Ihr Zahlungsablauf wahrscheinlich um die Illusion einer „einzigen Transaktion“ herum entworfen.

Was aus diesem Teil bleiben sollte

  1. Eine Zahlung ist nicht die Operation eines einzigen Services; sie ist eine Koordination, bei der sich Warenkorb, Bestand, Provider-Gateway und Ledger auf dieselbe Tatsache einigen.
  2. Eine synchrone HTTP-Kette vervielfacht Unsicherheit mit jedem zusätzlichen Schritt; ein Timeout ist kein Ergebnis, sondern ein Unbekanntes.
  3. Der PSP ist nicht Teil Ihrer Transaktionsgrenze; Sie sprechen mit ihm über einen Event-Vertrag, nicht über eine synchrone Sperre.
  4. Eventual Consistency ist kein Mangel — es ist eine ehrliche Reflexion darüber, wie sich die Außenwelt, besonders Ihr PSP, tatsächlich verhält.

Entwerfen Sie Ihr Zahlungssystem als „sofort und aus einem Guss“, und die Produktion antwortet mit „verzögert und aus vielen Teilen“.

FAQ

Häufige Fragen

Was ist Checkout Orchestrator?

Koordiniert die Schritte eines Bestellablaufs (Warenkorb, Zahlung, Bestand, Bestätigung); hält selbst kein Geld und keinen Bestand, nur Entscheidungen und ihre Reihenfolge.

Was ist Provider-Gateway?

Die Abstraktionsschicht, die einen realen Zahlungsanbieter (PSP) in das interne Domänenmodell übersetzt.

Stimmt es, dass „Ein Zahlungsablauf ist die Funktion eines Services“?

Ein Zahlungsablauf ist Koordination zwischen mehreren unabhängigen Services

Was legt dieser Teil fest?

Dieser Teil erklärt, warum ein Zahlungsablauf als Problem verteilter Systeme entworfen werden muss — nicht als Funktion eines einzelnen Services. Eine Zahlung ist nicht die Operation eines einzigen Services; sie ist eine Koordination, bei der sich Warenkorb, Bestand, Provider-Gateway und Ledger auf dieselbe Tatsache einigen. Wenn ein Checkout-Flow in einer E-Commerce-Plattform „Kunden belasten“ sagt, müssen in Wirklichkeit fünf verschiedene Systeme sich auf dieselbe Tatsache einigen: Ist der Warenkorb eingefroren, ist Bestand verfügbar, hat das Provider-Gateway das Geld erhalten, ist die Bestellung bestätigt, stimmt der Ledger-Eintrag. Nichts davon lebt in einem einzigen Prozess oder einer einzigen Transaktion.

Gelernte Engineering-Prinzipien

  • Ein Zahlungsablauf ist Koordination zwischen unabhängigen Systemen, nicht die Funktion eines einzelnen Services.
  • Der PSP liegt außerhalb Ihrer Transaktionsgrenze; Sie sprechen mit ihm über einen Event-Vertrag, nicht über eine synchrone Sperre.
  • Eventual Consistency ist keine Schwäche, sondern die ehrliche Antwort im Design auf das tatsächliche Verhalten von Netzwerken und externen Anbietern.

Weiterlesen

Weiterlesen

Nachster Teil der Serie

Aus derselben Serie

Aus derselben Serie

Paylaş