Playbook

Aufbau eines Zahlungsabgleich-Workers (Aufbau Eines Zahlungsabgleich Workers)

Wie Sweeper Drift heilen: Der PSP meldet erfolgreich, während der lokale Datensatz abgelaufen ist — und wie gealterte FinalizePending-Einträge aufgelöst werden.

Verteilte Payment Engine (Distributed Payment Engine)

Teil 14 von 22

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

Distributed payment engine architecture diagram

Der vorherige Teil hat gezeigt, wie ein Lease sicher die Besitzverhältnisse eines Jobs herstellt. Doch selbst der stabilste Lease kann eine Tatsache nicht ändern: Manchmal läuft ein Worker in einen Timeout, bevor er eine endgültige Antwort vom PSP erhält, der Prozess stürzt ab, oder ein Lease läuft ab und der Job wird als 'expired' markiert — genau in dem Moment, in dem die Zahlung auf Seiten des PSP tatsächlich erfolgreich war.

Genau deshalb gibt es den Abgleich-Worker: einen Sweeper, der periodisch nach Drift zwischen dem lokalen System und den eigenen Aufzeichnungen des PSP sucht und diese korrigiert.

Lokaler Datensatz: Payment #123 → Expired
PSP-Datensatz:      Payment #123 → Succeeded
                  │
                  ▼
        Abgleich-Worker erkennt die Drift
                  │
                  ▼
        Lokaler Datensatz → korrigiert auf Captured

Wo die Begriffe zuerst auftauchen

📦 Reconciliation (Abgleich)
Der Prozess, zwei unabhängige Quellen (lokales System, PSP) zu vergleichen und Unterschiede zu korrigieren.

📦 Drift
Wenn der lokale Zustand vom tatsächlichen Datensatz des PSP abweicht, meist durch einen Fehler oder Timeout.

📦 Sweeper
Ein Hintergrundjob, der periodisch nach Datensätzen sucht, die einem Kriterium entsprechen — etwa 'gealtert' oder 'abgelaufen'.

📦 FinalizePending
Ein Zwischenstatus, der bedeutet, dass die Zahlung beim PSP bereits abgeschlossen sein könnte, das lokale System aber noch keinen endgültigen Zustand erreicht hat.

Abgleich ist keine Echtzeitkorrektur, sondern ein Sicherheitsnetz. Der Hauptpfad (Webhook, synchrone Antwort) funktioniert meist korrekt; der Abgleich räumt auf, was außerhalb dieses 'meist' liegt.

Die eigentlichen Quellen von Drift

Drift entsteht selten zufällig; meist stammt sie aus wenigen wiederkehrenden Szenarien: Ein Worker sendet die Anfrage, und der Prozess stürzt ab, bevor die Antwort gelesen wird; ein Netzwerkfehler führt dazu, dass die Antwort nie ankommt, obwohl der PSP die Operation abgeschlossen hat; oder die Lease-TTL ist kürzer als die Antwortzeit des PSP, und der Job wird zu früh als abgelaufen markiert.

Szenario 1: Worker abgestürzt
  Anfrage gesendet → PSP hat verarbeitet → Worker hat die Antwort nie gelesen

Szenario 2: Netzwerkfehler
  Anfrage gesendet → PSP hat verarbeitet → Antwort ist auf dem Weg verloren gegangen

Szenario 3: Lease zu früh abgelaufen
  Anfrage gesendet → PSP antwortete langsam → Lease abgelaufen → Stuck Watcher hat den Job zurückgesetzt → aber der PSP war schon erfolgreich

Alle drei Szenarien teilen dieselbe Struktur: Der lokale Datensatz verbleibt in einem unklaren oder falschen Status, während der eigene Datensatz des PSP das tatsächliche Ergebnis bereits kennt.

Die Abfrage des Sweepers: welche Datensätze durchsucht werden

Ein Abgleich-Worker vergleicht nicht ständig jeden Datensatz mit dem PSP — das wäre teuer und unnötig. Er zielt nur auf 'verdächtige' Datensätze: solche, die ein bestimmtes Alter überschritten haben und noch in einem Zwischenstatus (FinalizePending, Expired, zu lange in Processing) verbleiben.

SELECT id, provider_ref FROM payments
WHERE status IN ('FinalizePending', 'Expired')
  AND updated_at < now() - interval '10 minutes';

Die Schwelle von '10 Minuten' ist nicht willkürlich; sie stammt aus einem SLA dafür, wie lange der normale Pfad zur Auflösung brauchen sollte. Jüngere Datensätze sind noch nicht 'verdächtig', sondern vielleicht nur langsam.

Den PSP abfragen und entscheiden

Für jeden Kandidaten prüft der Worker die Status-Abfrage-API des PSP (falls vorhanden) oder die eigene archivierte Webhook-Historie. Drei Ergebnisse sind möglich:

PSP: Succeeded → lokalen Datensatz auf Captured setzen, semantisches Event veröffentlichen
PSP: Failed    → lokalen Datensatz auf Failed setzen
PSP: Not Found / Unknown → als tatsächlich ungelöst behandeln, an den Recovery-Flow weiterleiten

Entscheidend ist, dass auch dieser Übergang idempotent sein muss: Selbst wenn der Abgleich-Worker denselben Datensatz zweimal verarbeitet, darf sich das Ergebnis nicht ändern (ist der Datensatz bereits Captured, darf nicht erneut dasselbe Event veröffentlicht werden).

Alerting: ein Sweeper sollte nicht still laufen

Jede vom Abgleich-Worker gefundene Drift sollte ein Observability-Signal erzeugen. Ein plötzlicher Anstieg der Drift-Zahl deutet meist auf ein Problem im Hauptpfad hin (Webhook-Verarbeitung, Lease-TTL, Netzwerk) — Abgleich sollte dieses Problem sichtbar machen, nicht verstecken.

Metrik Was sie aussagt
Durchsuchte Kandidaten-Datensätze Wie 'sauber' der Hauptpfad läuft
Korrigierte Drift-Datensätze Tatsächliches Volumen der Dateninkonsistenz
Weiterhin ungelöste Datensätze Die Warteschlange für manuelle Prüfung

Häufig verwechselte Unterschiede

❌ Abgleich ist eine Echtzeitkorrektur
✓ Abgleich ist ein periodisches Sicherheitsnetz, kein Ersatz für den Hauptpfad

❌ Die Drift-Zahl sollte null sein, sonst ist das System defekt
✓ Eine niedrige, stabile Drift-Rate ist normal; ein steigender Wert ist das eigentliche Signal

❌ Jeder Datensatz sollte mit dem PSP verglichen werden
✓ Nur gealterte Datensätze im Zwischenstatus sollten anvisiert werden

Hauptpfad vs. Abgleich-Worker

Dimension Hauptpfad (Webhook/synchron) Abgleich-Worker
Geschwindigkeit Sekunden Minuten bis Stunden
Umfang jede Zahlung nur verdächtige/gealterte Datensätze
Zweck der normale Weg Sicherheitsnetz

Checkliste beim Aufbau eines Abgleich-Workers

  1. Leitet sich die 'gealtert'-Schwelle in der Sweeper-Abfrage aus einem echten Geschäfts-SLA ab, oder ist sie willkürlich?
  2. Hält die Abfrage des PSP die eigene Rate-Limit- und Retry-Strategie ein?
  3. Ist die Drift-Korrektur idempotent — bleibt das Ergebnis unverändert, wenn derselbe Datensatz zweimal verarbeitet wird?
  4. Landen unlösbare Datensätze (auch dem PSP unbekannt) in einer sichtbaren Warteschlange für manuelle Prüfung?
  5. Wird die Drift-Zahl als Metrik verfolgt, die bei plötzlichem Anstieg alarmiert?

Was bleiben soll

  1. Abgleich ergänzt den Hauptpfad, ersetzt ihn nicht; der Hauptpfad funktioniert meistens, der Sweeper räumt den Rest auf.
  2. Der Sweeper zielt auf verdächtige Datensätze nach Alter und Status, nicht auf jeden Datensatz.
  3. Jede Korrektur nach einer PSP-Abfrage muss idempotent sein und der eigenen Retry-Disziplin folgen.
  4. Die Drift-Zahl ist ein Observability-Signal; sie sollte still gegen null tendieren, ein plötzlicher Anstieg ist eine Warnung.

Ein Abgleich-Worker zeigt nicht, wie perfekt ein System ist — er zeigt, wie ehrlich es ist.

Der nächste Teil behandelt die unangenehmste Form dieser Drift: Der Kunde wurde beim PSP belastet, aber es existiert lokal keine Bestellung — und wie man das sicher heilt.

FAQ

Häufige Fragen

Was ist Reconciliation (Abgleich)?

Der Prozess, zwei unabhängige Quellen (lokales System, PSP) zu vergleichen und Unterschiede zu korrigieren.

Was ist Drift?

Wenn der lokale Zustand vom tatsächlichen Datensatz des PSP abweicht, meist durch einen Fehler oder Timeout.

Stimmt es, dass „Abgleich ist eine Echtzeitkorrektur“?

Abgleich ist ein periodisches Sicherheitsnetz, kein Ersatz für den Hauptpfad

Was legt dieser Teil fest?

Genau deshalb gibt es den Abgleich-Worker: einen Sweeper, der periodisch nach Drift zwischen dem lokalen System und den eigenen Aufzeichnungen des PSP sucht und diese korrigiert. Abgleich ergänzt den Hauptpfad, ersetzt ihn nicht; der Hauptpfad funktioniert meistens, der Sweeper räumt den Rest auf. Der vorherige Teil hat gezeigt, wie ein Lease sicher die Besitzverhältnisse eines Jobs herstellt. Doch selbst der stabilste Lease kann eine Tatsache nicht ändern: Manchmal läuft ein Worker in einen Timeout, bevor er eine endgültige Antwort vom PSP erhält, der Prozess stürzt ab, oder ein Lease läuft ab und der Job wird als 'expired' markiert — genau in dem Moment, in dem die Zahlung auf Seiten des PSP tatsächlich erfolgreich war.

Gelernte Engineering-Prinzipien

  • Abgleich ergänzt den Hauptpfad, ersetzt ihn nicht.
  • Der Sweeper zielt auf gealterte, verdächtige Datensätze, nicht auf jeden.
  • Die Drift-Zahl ist ein Signal, das gegen null tendieren sollte, nicht verborgen bleiben.

Weiterlesen

Weiterlesen

Nachster Teil der Serie

Nachster Teil der Serie

Aus derselben Serie

Paylaş