Playbook

Zahlungsbeleg vs. Zahlungsstatus (Zahlungsbeleg Versus Zahlungsstatus)

Beleg (Evidence) ist, was der PSP sagte. Status (State) ist, was Sie entschieden haben. Vermischen Sie beide, weiß die Wiederherstellung nicht, wem sie…

Verteilte Payment Engine (Distributed Payment Engine)

Teil 8 von 22

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

Distributed payment engine architecture diagram

Zwei verschiedene Fragen, zwei verschiedene Datensätze

„Was hat der PSP gesagt?“ und „was haben wir entschieden?“ sehen ähnlich aus, sind aber zwei völlig unterschiedliche Fragen. Die Antwort auf die erste ist Evidence (Beleg): der rohe Webhook vom PSP, die API-Antwort, der Zeitstempel — ein unveränderlicher Datensatz. Die Antwort auf die zweite ist State (Status): die Entscheidung, die Sie durch die Kombination dieses Belegs mit Ihren Geschäftsregeln getroffen haben — ist die Zahlung Captured, ist der Checkout Completed.

Evidence (Beleg)              State (Status)
Die rohe Antwort des PSP  →   Ihre Entscheidung
Unveränderlich, Append-only → Veränderlich, Entscheidungstabelle
„Was ist passiert“        →   „Was haben wir entschieden“

Dieser Teil erklärt, warum Sie diese beiden nie im selben Datensatz halten sollten, und warum diese Trennung bei der Wiederherstellung lebensrettend ist.

Begriffe, dort definiert, wo sie zuerst auftauchen

📦 Evidence (Beleg)
Die rohe Tatsache, die ein externes System (der PSP) Ihnen meldet, gespeichert ohne Interpretation oder Änderung.

📦 State (Status)
Die Entscheidung, die Sie — wie in der Zustandsmaschine aus Teil zwei und vier definiert — durch Kombination von Evidence mit Ihren Geschäftsregeln treffen.

📦 Append-only Log
Eine Speicherform, bei der Datensätze nur hinzugefügt, nie überschrieben oder gelöscht werden.

📦 Source of Truth vs. Derived Truth
Erstere ist die rohe, unbestreitbare Tatsache; letztere die interpretierte, aus dieser Tatsache abgeleitete Entscheidung.
📦 Reconciliation
Der Prozess, Evidence-Datensätze erneut zu lesen, um zu prüfen, ob der aktuelle State noch mit ihnen übereinstimmt.

Das klarste Beispiel für diese Trennung: Der vom PSP gesendete Webhook-Payload ist Evidence; dass Sie diesen Payload lesen und Payment.Status = Captured schreiben, ist eine State-Entscheidung. Evidence ändert sich nie; State kann aktualisiert werden, wenn neue Evidence eintrifft.

Warum die beiden nicht in derselben Tabelle leben können

Manche Systeme schreiben einen eingehenden PSP-Webhook direkt über die payments-Tabelle: Trifft ein neuer Webhook ein, wird die entsprechende Zeile aktualisiert, der alte Wert ist weg. Bei diesem Design können Sie die Frage „Was genau hat der PSP gesagt“ nicht mehr beantworten — nur noch „Was war unsere letzte Interpretation“.

Falsches Modell:
payments
id | status     | raw_payload
1  | Captured   | {...Inhalt des letzten Webhooks, vorherige überschrieben...}

Das ist genau die Information, die Sie in einem Incident am meisten brauchen würden — die historische Beleg-Kette —, die Sie hier verlieren.

Das richtige Modell: zwei getrennte Speicher

Evidence lebt in ihrer eigenen Append-only-Tabelle; jeder neue Webhook oder jede neue API-Antwort wird als neue Zeile hinzugefügt, keine Zeile wird je aktualisiert oder gelöscht. State lebt in einer separaten Tabelle als die aktuelle, aus dieser Evidence abgeleitete Entscheidung.

payment_evidence (Append-only)
id | payment_id | source | received_at | raw_payload
1  | pay_42     | psp    | t1           | {...authorize...}
2  | pay_42     | psp    | t2           | {...captured...}
3  | pay_42     | psp    | t5           | {...captured (Duplikat)...}

payments (State)
id     | status
pay_42 | Captured   ← abgeleitet aus Evidence #2, erneut bestätigt durch #3

Mit dieser Trennung „vergisst“ die State-Zeile nie, wann und warum sie sich geändert hat — denn die Evidence, die sie erzeugt hat, ist noch da.

Warum Wiederherstellung Evidence liest und State nicht vertraut

Nach einem Incident (ein Worker-Absturz, ein fehlerhaftes Deployment, eine verdächtige Inkonsistenz), wenn Sie Ihr System in einen „korrekten“ Zustand zurückbringen müssen, ist es riskant, sich auf den aktuellen State zu verlassen — denn genau dieser State könnte das sein, was der Incident beschädigt hat. Stattdessen ist es zuverlässiger, das Evidence-Log von vorne zu lesen und den State neu abzuleiten (ein Replay).

Wiederherstellungsprozess
  1. Alle Datensätze zu pay_42 aus payment_evidence chronologisch lesen
  2. Jede Evidence erneut durch die Geschäftsregeln verarbeiten (durch die Guards)
  3. Den daraus abgeleiteten State mit dem aktuellen Wert in der payments-Tabelle vergleichen
  4. Bei einer Abweichung, welcher Wert richtig ist, anhand der Evidence entscheiden — nicht anhand des State

Dieser Prozess ist die Grundlage der Reconciliation-Worker, die wir später in dieser Serie behandeln: Ist der State zweifelhaft, ist Evidence immer der Schiedsrichter.

Evidence niemals „interpretiert“ speichern

Eine letzte Falle: Manche Systeme „bereinigen“ Evidence sogar beim Speichern — löschen für unnötig gehaltene Felder, normalisieren das Format. Das zerstört den eigentlichen Wert von Evidence — genau, byte für byte, zu wissen, was der PSP gesagt hat. Evidence sollte die rohe, unveränderte Antwort sein, die Ihnen der PSP gegeben hat; Interpretation und Normalisierung gehören zum State-Ableitungsschritt, nicht zur Evidence selbst.

Die am häufigsten verwechselten Zuordnungen

❌ Evidence und State können sich eine Zeile teilen, eine überschreibt die andere
✓ Evidence ist Append-only; State lebt in einer separaten Tabelle, abgeleitet aus Evidence

❌ Den Webhook-Payload vor dem Speichern zu „bereinigen“ ist harmlos
✓ Bereinigte Evidence verliert die Information, was der PSP genau gesagt hat

❌ Sich in einem Incident auf den aktuellen State zu verlassen ist der schnellste Weg
✓ State ist während eines Incidents zweifelhaft; eine Neuableitung aus Evidence (Replay) ist zuverlässiger

❌ Evidence dient nur Debugging/Logging, für Geschäftsentscheidungen nicht nötig
✓ Evidence ist die einzige zuverlässige Quelle für Reconciliation und Wiederherstellung

Checkliste zur Prüfung Ihrer Evidence/State-Trennung

  1. Wird der rohe Webhook-Payload des PSP in einer separaten, Append-only-Tabelle gespeichert, oder überschreibt er die payments-Tabelle?
  2. Überschreibt ein zweiter oder dritter Webhook für dieselbe Zahlung den ersten Datensatz, oder fügt er eine neue Evidence-Zeile hinzu?
  3. Haben Sie einen Prozess, der das Evidence-Log erneut abspielen kann, um den State neu abzuleiten, wenn eine State-Inkonsistenz vermutet wird?
  4. „Bereinigt“ oder normalisiert irgendein Schritt Evidence vor dem Speichern? Falls ja, bewahren Sie die Rohdaten separat auf?
  5. Können Sie nachträglich verfolgen, aus welchem Evidence-Datensatz eine bestimmte Zeile in Ihrer State-Tabelle abgeleitet wurde?

Beantworten Sie eine dieser fünf Fragen mit „nein“, können Sie in einem Incident die Frage „Was hat der PSP wirklich gesagt“ möglicherweise nicht beantworten.

Was aus diesem Teil bleiben sollte

  1. Evidence ist die rohe, unveränderliche Tatsache, die der PSP Ihnen gemeldet hat; State ist die Entscheidung, die Sie durch Kombination dieser Tatsache mit Ihren Geschäftsregeln getroffen haben.
  2. Evidence muss Append-only sein; ein neuer Webhook fügt eine neue Zeile hinzu, er überschreibt nie die alte.
  3. Wiederherstellungs- und Reconciliation-Prozesse sollten dem aktuellen State nicht vertrauen; sie sollten das Evidence-Log erneut lesen und den State neu ableiten.
  4. Evidence beim Speichern zu „bereinigen“ zerstört die Information, was der PSP genau gesagt hat; die Rohdaten müssen immer erhalten bleiben.

State ist Ihre heutige Interpretation; Evidence ist der Zeuge, der sich nie ändert. Wenn Sie in einem Incident den Zeugen statt Ihre eigene Interpretation anzweifeln, verlieren Sie.

FAQ

Häufige Fragen

Was ist Evidence (Beleg)?

Die rohe Tatsache, die ein externes System (der PSP) Ihnen meldet, gespeichert ohne Interpretation oder Änderung.

Was ist State (Status)?

Die Entscheidung, die Sie — wie in der Zustandsmaschine aus Teil zwei und vier definiert — durch Kombination von Evidence mit Ihren Geschäftsregeln treffen.

Stimmt es, dass „Evidence und State können sich eine Zeile teilen, eine überschreibt die andere“?

Evidence ist Append-only; State lebt in einer separaten Tabelle, abgeleitet aus Evidence

Was legt dieser Teil fest?

Dieser Teil erklärt, warum Sie diese beiden nie im selben Datensatz halten sollten, und warum diese Trennung bei der Wiederherstellung lebensrettend ist. Evidence ist die rohe, unveränderliche Tatsache, die der PSP Ihnen gemeldet hat; State ist die Entscheidung, die Sie durch Kombination dieser Tatsache mit Ihren Geschäftsregeln getroffen haben. „Was hat der PSP gesagt?“ und „was haben wir entschieden?“ sehen ähnlich aus, sind aber zwei völlig unterschiedliche Fragen. Die Antwort auf die erste ist Evidence (Beleg): der rohe Webhook vom PSP, die API-Antwort, der Zeitstempel — ein unveränderlicher Datensatz. Die Antwort auf die zweite ist State (Status): die Entscheidung, die Sie durch die Kombination dieses Belegs mit Ihren Geschäftsregeln getroffen haben — ist die Zahlung `Captured`, ist der Checkout `Completed`.

Gelernte Engineering-Prinzipien

  • Evidence ist die rohe, unveränderliche Tatsache des PSP; State ist die Entscheidung, die Sie durch Kombination dieser Tatsache mit Geschäftsregeln getroffen haben — beide sind nie derselbe Datensatz.
  • Evidence muss immer Append-only sein; neue Information wird neben der alten hinzugefügt, nie über sie geschrieben.
  • Wiederherstellung und Reconciliation müssen der unveränderlichen Evidence vertrauen, nie dem gerade zweifelhaften State.

Weiterlesen

Weiterlesen

Nachster Teil der Serie

Nachster Teil der Serie

Aus derselben Serie

Paylaş