1 Punkte von GN⁺ 2 시간 전 | 1 Kommentare | Auf WhatsApp teilen
  • Statt die Zahlungs-API überall direkt aus der Produktlogik aufzurufen, protokolliert exe Zustandsänderungen als abrechenbare Fakten (billable facts) und gleicht den bestätigten Zustand anschließend mit Stripe ab.
  • In der bisherigen Struktur waren Datenbanktransaktionen und Aufrufe der Zahlungs-API miteinander verflochten, sodass Ausnahmen wie partielle Fehlschläge, inkonsistente Abonnementzustände oder abgelehnte Zahlungen sogar den Produktfluss erschütterten.
  • Wenn Team-Sitze hinzukommen, wird der Zustand als dirty markiert; ein nachgelagerter Worker berechnet dann gemäß den Geschäftsregeln die Anzahl und aktualisiert die Stripe-Abonnementmenge nur, wenn sie sich geändert hat.
  • Durch die Entkopplung der Zahlung hängt das Onboarding neuer Teammitglieder nicht mehr von Zahlungscode ab, und Änderungen an den Regeln zur Sitzberechnung beeinflussen den Einladungs- und Beitrittsfluss nicht.
  • Dieselbe Abgleichsstruktur wird auch auf nutzungsbasierte Abrechnung wie aktive VMs und Festplattennutzung sowie auf In-App-Käufe unter iOS angewendet, sodass Produktereignisse erhalten bleiben und nur die provider-spezifischen Integrationen ausgetauscht werden müssen.

Zahlungslogik aus dem Produktfluss herauslösen

  • Wenn Zahlungslogik mit allgemeiner Business-Logik vermischt wird, verteilt sich entsprechender Code über alle kritischen Pfade, die Abrechnung benötigen, und auch die Preisstruktur wird fragil und schwer änderbar.
  • exe verfolgt das Ziel, dass Zahlungswissen nicht von einer einzelnen Person monopolisiert wird und grundsätzlich jede Person den entsprechenden Code ändern kann, während komplexe Ausnahmen von spezialisierten Zuständigen behandelt werden.
  • Die anfängliche Abrechnung von Team-Sitzen war von der Annahme der Einladung bis zur Zahlung als ein großer Ablauf zusammengebunden.
    • Nutzer akzeptieren eine Einladung, bestätigen ihr Konto und treten dann dem Team bei.
    • Sie erhalten Zugriff auf die gemeinsame VM und bekommen je nach Tarif Computing-Ressourcen zugewiesen.
    • In diesem Prozess wird auch die Zahlungs-API aufgerufen.
  • Werden Datenbankänderungen und externe API-Aufrufe so gekoppelt, kann es zu partiellen Fehlschlägen kommen, bei denen nur eine Seite erfolgreich ist.
    • Der Status des Team-Abonnements kann inkonsistent werden.
    • Die Zahlung für zusätzliche Sitze kann abgelehnt werden.
    • Je mehr Ausnahmen sich ansammeln, desto fragiler wird die Gesamtstruktur.

Abrechenbare Fakten und nachgelagerter Abgleich

  • Abrechenbare Fakten sind atomare Vorgänge, die anzeigen, dass sich ein bestimmter Zustand geändert hat.
    • Zuerst wird die Produktlogik ausgeführt, um den neuen Zustand der Ressourcen festzulegen.
    • Danach wird auf Basis der bestätigten Fakten der Zustand beim Zahlungsanbieter abgeglichen.
    • Stripe braucht nicht den Weg zu diesem Zustand, sondern nur die Endmenge.
  • Abgleich von Team-Sitzen

    • Wird eine Einladung angenommen, wird der Status der Team-Sitze als dirty markiert.
    • Ein nachgelagerter Worker erkennt den dirty-Zustand und berechnet nach den Geschäftsregeln die Zu- oder Abnahme der Sitze.
    • Nur wenn sich die Menge geändert hat, wird die Abonnementmenge bei Stripe aktualisiert.
    • Da das Hinzufügen von Teammitgliedern und der Zahlungscode getrennt sind, bricht die Abrechnung nicht mit, selbst wenn der Einladungsfluss neu geschrieben wird; auch die Methode zur Sitzberechnung kann unabhängig geändert werden.
  • Nutzungsbasierte Abrechnung und In-App-Käufe

    • Derselbe Abgleichsprozess wird auf jede nutzungsbasierte Abrechnung angewendet.
      • Das System zeichnet Fakten über aktive VMs und Festplattennutzung auf.
      • Ein Metering-Worker gleicht sie mit dem Zustand beim Zahlungsanbieter ab.
      • Selbst wenn neue Abrechnungsmodelle hinzukommen, bleiben die Fakten unverändert; nur die jeweilige Abstimmung mit den einzelnen APIs unterscheidet sich.
    • Die iOS-App übermittelt ebenfalls nur den Fakt, dass jemand per In-App-Kauf ein Abonnement abgeschlossen hat; der tatsächliche Zahlungsstatus wird erst danach abgeglichen.
    • Die Zahlungsstruktur ist damit zu einem Bereich geworden, den auch andere Teammitglieder bearbeiten können, und Produktänderungen wie am Einladungsfluss beschädigen das Abrechnungssystem deutlich seltener.

1 Kommentare

 
GN⁺ 2 시간 전
Meinungen auf Lobste.rs
  • Der Kern des Beitrags, Änderungen asynchron zu erkennen und zu verarbeiten, eignet sich gut, um Kopplung zu reduzieren und Seiteneffekte umzusetzen.
    Allerdings sind LLMs eher ein Werkzeug, das die Verteilung von Code über viele Stellen hinweg beschleunigt, statt sie zu verhindern, und können daher leicht zu architektonischer Schuld werden. Fraglich ist auch, wie man Code prüfen soll, der schneller erzeugt wird, als man ihn verstehen kann; die Stelle, dass Exe nicht einmal Code-Reviews durchführt, macht das noch beunruhigender.

    • Man sollte im Hinterkopf behalten, dass die Tech-Branche, die ohnehin selten besonders ernsthaft war, derzeit eine auffallend unseriöse Phase durchläuft.
    • Aus Sicht jemandes, der mit Abrechnungssystemen arbeitet, ist das ein ziemlich beängstigender Ansatz. Eine Billing-Plattform besteht aus mehreren klar abgegrenzten Kontexten, und da LLMs Domänengrenzen nicht gut einhalten, kann das großen Schmerz verursachen.
    • Ich hatte eher den Eindruck, dass Code nicht „auch mit LLMs“, sondern gerade mit LLMs stärker verstreut wird.
    • Dieses Zitat kenne ich nicht von Orwell, sondern von Upton Sinclair.
  • Diese Architektur ist zwar interessant, aber unklar bleibt, wie sie das am Anfang des Beitrags geschilderte Problem löst. Wenn eine Zahlung abgelehnt wird, scheint man eher unbezahlte Ressourcen zuerst bereitzustellen, statt die Bezahlung aller Ressourcen sicherzustellen.
    Ein Billing-Worker könnte die Tatsache declined veröffentlichen und Ressourcen zurückholen, aber im Vergleich zu einem sauberen unidirektionalen Ablauf entsteht dadurch eine zyklische Struktur. Für einen Computing-Dienst wie Exe, der monatlich abrechnet, passt das wohl gut; für Unternehmen, die physische Geräte versenden oder Seats anderer Dienste weiterverkaufen, ist es ein schwer akzeptabler Kompromiss.

    • Es handelt sich um ein softwarezentriertes Abrechnungsmodell, bei dem das Produkt abstrakt und austauschbar ist. Nutzungsbasierte Abrechnung basiert auf Analysedaten darüber, dass ein abrechenbares Ereignis stattgefunden hat; das Abrechnungssystem sollte diese aggregieren und daraus konsistente Rechnungspositionen erstellen. Da abrechenbare Ereignisse an vielen Stellen entstehen können, ist es auch gesund, sie aus dem Produktcode herauszulösen.
      Allerdings beantwortet das nicht direkt, wie fehlgeschlagene API-Aufrufe oder Datenbanktransaktionen, anomale Abo-Zustände oder abgelehnte Seat-Zahlungen behandelt werden. Auch Probleme bleiben bestehen, bei denen ein Refactoring die Analytics-Erfassung kaputtmacht, eine bestimmte Zeile nicht mehr als geändert markiert wird oder in einem neuen Pfad die Änderungsmarkierung vergessen wird.
      Auch abrechnungsbezogener Zustand innerhalb des Produkts, etwa Limits für Seats und kostenlose Kontingente, maximale Ausgabenbeträge oder das Abbuchen von Prepaid-Guthaben, wird dadurch nicht gelöst. Der Produktdienst kann Events veröffentlichen und der Billing-Dienst den Compliance-Status zurück ins Produkt spiegeln, aber dann hat man in einem zustandsbehafteten verteilten System zwei Akteure.
  • Es mag so aussehen, als wolle Stripe nur eine einzige Zahl, aber ab einer gewissen Größenordnung kann die Bereitstellung von Einzelposten einer Zahlung Interchange-Gebühren senken und die Autorisierungsrate erhöhen.

  • Exes Ansatz, keine Code-Reviews durchzuführen, ist erfrischend. Dann würde mich interessieren, wie Releases und Tests betrieben werden.