Datenbankschema für Pläne und Berechtigungen bei Upgrades und Add‑ons
Datenbankschema für Pläne und Berechtigungen, das Upgrades, Add‑ons, Trials und Widerrufe ohne hartkodierte Regeln mit klaren Tabellen und Zeitfenstern unterstützt.

Warum Pläne und Features schnell unordentlich werden
Auf einer Preisseite wirken Pläne einfach: Basic, Pro, Enterprise. Das Chaos beginnt in dem Moment, in dem du diese Namen in echte Zugriffsregeln in deiner App übersetzen willst.
Hartkodierte Feature‑Prüfungen (wie if plan = Pro then allow X) funktionieren für die erste Version. Dann ändert sich das Pricing. Ein Feature rutscht von Pro zu Basic, ein neues Add‑on erscheint oder ein Sales‑Deal enthält ein individuelles Bundle. Plötzlich hast du dieselbe Regel kopiert in APIs, UI, Mobile‑Apps und Hintergrundjobs. Du änderst eine Stelle und vergisst eine andere. Die Nutzer merken es.
Ein zweites Problem ist Zeit. Subscriptions sind kein statisches Label; sie ändern sich innerhalb eines Zyklus. Jemand upgraded heute, downgrades nächsten Monat, pausiert oder kündigt bei noch verbleibender bezahlter Zeit. Wenn deine Datenbank nur den „aktuellen Plan“ speichert, verlierst du die Timeline und kannst später einfache Fragen nicht mehr beantworten: Was hatten sie letzten Dienstag? Warum hat der Support eine Rückerstattung genehmigt?
Add‑ons verschlimmern das, weil sie Pläne durchschneiden. Ein Add‑on kann zusätzliche Seats freischalten, ein Limit aufheben oder ein bestimmtes Feature aktivieren. Leute können es auf jedem Plan kaufen, später entfernen oder nach einem Downgrade behalten. Wenn die Regel im Code steckt, wächst die Ansammlung von Spezialfällen.
Typische Situationen, die naive Designs brechen:
- Upgrade mid‑cycle: Zugriff sollte sofort ändern, Abrechnungs‑Prorationen folgen ggf. anderen Regeln.
- Geplantes Downgrade: Zugriff kann bis zum Ende des bezahlten Zeitraums „höher“ bleiben.
- Grandfathering: Bestehende Kunden behalten ein Feature, das neue Kunden nicht bekommen.
- Custom‑Deals: Ein Account bekommt Feature A, aber nicht Feature B, obwohl derselbe Planname gilt.
- Prüfbedarf: Support, Finanzen oder Compliance fragen „was genau war wann aktiviert?"
Das Ziel ist simpel: ein flexibles Zugriffsmodell, das mit Pricing mitwächst, ohne dass du bei jeder Änderung Geschäftslogik umschreiben musst. Du willst einen Ort, an dem du fragen kannst „dürfen sie das?“ und eine Datenspur, die die Antwort erklärt.
Am Ende dieses Artikels hast du ein Schema‑Pattern zum Kopieren: Pläne und Add‑ons werden zu Eingaben, und Entitlements werden zur einzigen Quelle der Wahrheit für Feature‑Zugriff. Der gleiche Ansatz passt auch zu No‑Code‑Buildern wie AppMaster, weil Regeln in Daten gehalten und konsistent vom Backend, der Web‑App und Mobil‑Apps abgefragt werden können.
Wichtige Begriffe: Plan, Add‑on, Entitlement und Zugriff
Viele Subscription‑Probleme beginnen als Vokabularproblem. Wenn alle dasselbe Wort unterschiedlich verwenden, wird dein Schema voller Spezialfälle.
Diese Begriffe solltest du getrennt halten:
- Plan: Das Standardpaket, das jemand beim Abonnieren erhält (z. B. Basic oder Pro). Ein Plan setzt meist Basislimits und eingeschlossene Features.
- Add‑on: Ein optionaler Kauf, der die Basis verändert (z. B. „extra Seats“ oder „erweiterte Berichte“). Add‑ons sollten an‑ und abhängbar sein, ohne den Plan zu ändern.
- Entitlement: Das endgültige, berechnete „was sie jetzt haben“, nach Kombination von Plan + Add‑ons + Overrides. Das sollte deine App abfragen.
- Permission (oder Capability): Eine konkrete Aktion, die jemand ausführen kann (z. B. „Daten exportieren“ oder „Billing verwalten“). Permissions hängen oft von Rolle plus Entitlements ab.
- Access: Das reale Ergebnis, wenn Regeln durchgesetzt werden (der Screen zeigt oder versteckt ein Feature, ein API‑Call wird erlaubt oder blockiert, ein Limit greift).
Feature‑Flags sind verwandt, aber anders. Ein Feature‑Flag ist typischerweise ein Produkt‑Schalter für Rollouts, Experimente oder das Abschalten eines Features bei Vorfällen. Ein Entitlement ist kundenspezifischer Zugriff basierend auf Bezahlung oder Zuschüssen. Benutze Flags, wenn du Verhalten für Gruppen ändern willst, ohne Billing anzufassen. Benutze Entitlements, wenn Zugriff an Subscription, Rechnung oder Vertrag gebunden sein muss.
Der Scope ist eine weitere Verwechslungsquelle. Halte diese Ebenen klar:
- User: Eine einzelne Person. Nützlich für Rollen (Admin vs Member) und persönliche Limits.
- Account (Kunde): Die zahlende Einheit. Nützlich für Billing‑Infos und Subscription‑Besitz.
- Workspace (Projekt/Team): Der Ort, wo gearbeitet wird. Viele Produkte wenden Entitlements hier an (Seats, Storage, aktivierte Module).
Zeit ist wichtig, weil Zugriff sich ändert. Modellier sie direkt:
- Start und Ende: Ein Entitlement kann nur in einem Zeitfenster aktiv sein (Trial, Promo, Jahresvertrag).
- Geplante Änderung: Upgrades können sofort starten; Downgrades oft erst beim nächsten Renewal.
- Grace und Kündigung: Du kannst eingeschränkten Zugriff nach Zahlungsverzug erlauben, aber nur bis zu einem klaren Enddatum.
Beispiel: Ein Unternehmen ist auf Pro, fügt mid‑month „Advanced Reporting“ hinzu und plant später ein Downgrade zu Basic zum nächsten Abrechnungszeitpunkt. Der Plan ändert sich später, das Add‑on startet jetzt, und die Entitlement‑Schicht bleibt die einzige Stelle, die beantwortet: „Kann dieses Workspace heute Advanced Reports nutzen?“
Ein einfaches Kernschema für Pläne und Features
Ein gutes Schema trennt klein: was du verkaufst (Pläne und Add‑ons) von dem, was Leute tun können (Features). Wenn du diese beiden Ideen sauber hältst, werden Upgrades und neue Add‑ons Datenänderungen, nicht Code‑Neuschreibungen.
Praktische Kern‑Tabellen, die für die meisten Subscription‑Produkte funktionieren:
- products: die verkaufbaren Dinge (Basisplan, Teamplan, Extra‑Seats‑Add‑on, Priority‑Support‑Add‑on).
- plans: optional, falls du Pläne als speziellen Produkttyp mit plan‑spezifischen Feldern (Billing‑Interval, öffentliche Reihenfolge) möchtest. Viele Teams speichern Pläne einfach in
productsund nutzen eineproduct_type‑Spalte. - features: das Katalog der Fähigkeiten (API‑Zugriff, max_projects, Export, SSO, SMS‑Credits).
- product_features (oder
plan_features, wenn du Pläne trennst): eine Join‑Tabelle, die angibt, welche Features zu welchem Produkt gehören, meist mit einem Wert.
In dieser Join‑Tabelle steckt die meiste Kraft. Features sind selten nur an/aus. Ein Plan kann max_projects = 10 enthalten, während ein Add‑on +5 hinzufügt. Deshalb sollte product_features mindestens unterstützen:
feature_value(Zahl, Text, JSON oder separate Spalten)value_type(boolean, integer, enum, json)grant_mode(replace vs add), sodass ein Add‑on „+5 Seats“ hinzufügen kann statt den Basiswert zu überschreiben
Modelliere Add‑ons ebenfalls als Produkte. Der einzige Unterschied ist, wie sie gekauft werden. Ein Basisplan‑Produkt ist „eines pro Account“, während ein Add‑on Mengen erlauben kann. Beide mappen auf Features auf dieselbe Weise. Das vermeidet Spezialfälle wie „wenn Add‑on X dann Feature Y aktivieren“ verstreut im Code.
Features sollten Daten sein, keine Code‑Konstanten. Wenn du Feature‑Checks in mehreren Services hartkodierst, verschickst du früher oder später Inkonsistenzen (Web sagt ja, Mobile sagt nein, Backend widerspricht). Wenn Features in der Datenbank leben, kann die App eine konsistente Frage stellen und du rollst Änderungen durch Zeilenbearbeitung aus.
Namensgebung ist wichtiger als gedacht. Nutze stabile Identifikatoren, die niemals wechseln, auch wenn der Marketingname sich ändert:
feature_keywiemax_projects,sso,priority_supportproduct_codewieplan_starter_monthly,addon_extra_seats
Halte Anzeige‑Labels separat (feature_name, product_name). Wenn du AppMaster’s Data Designer mit PostgreSQL nutzt, zahlt sich das früh aus: du kannst gefahrlos neu generieren und Integrationen sowie Reporting stabil halten.
Die Entitlement‑Schicht: eine Stelle, die „dürfen sie?“ beantwortet
Die meisten Subscription‑Systeme kippen, wenn „was sie gekauft haben“ an einer Stelle gespeichert ist, aber „was sie tun dürfen“ in fünf verschiedenen Codepfaden berechnet wird. Die Lösung ist eine Entitlement‑Schicht: eine einzelne Tabelle (oder View), die effektiven Zugriff für ein Subjekt zu einem Zeitpunkt darstellt.
Wenn dein Ziel ein Schema ist, das Upgrades, Downgrades, Trials und Einzelzuschüsse übersteht, ist diese Schicht das, was alles vorhersehbar macht.
Eine praktische Entitlements‑Tabelle
Betrachte jede Zeile als einen Anspruch: „dieses Subjekt hat Zugriff auf dieses Feature mit diesem Wert, von Zeit X bis Zeit Y, aus Quelle Z.“ Eine übliche Form hat etwa diese Felder:
- subject_type (z. B. "account", "user", "org") und subject_id
- feature_id
- value (der effektive Wert für dieses Feature)
- source (woher es kam: "direct", "plan", "addon", "default")
- starts_at und ends_at (nullable ends_at für andauernden Zugriff)
Du kannst value unterschiedlich abbilden: eine Text/JSON‑Spalte plus value_type oder separate Spalten wie value_bool, value_int, value_text. Halte es pragmatisch und gut abfragbar.
Wertetypen, die die meisten Produkte abdecken
Features sind nicht immer an/aus. Diese Typen decken reale Billing‑ und Zugriffserfordernisse ab:
- Boolean: an/aus (
can_export= true) - Quoten‑Zahl: ein Limit (
seats= 10,api_calls= 100000) - Tier‑Level: eine Stufe (
support_tier= 2) - String: ein Modus oder eine Variante (
data_retention= "90_days")
Priorität: wie Konflikte gelöst werden
Konflikte sind normal. Ein Nutzer kann auf einem Plan sein, der 5 Seats erlaubt, ein Add‑on können 10 weitere Seats geben und Support kann manuell etwas gewähren.
Setze eine klare Regel und wende sie überall an:
- Direkter Zuschuss überschreibt Plan
- Dann Add‑ons
- Dann Defaults
Ein einfacher Ansatz: speichere alle Kandidatenzeilen (plan‑abgeleitet, addon‑abgeleitet, direkt) und berechne den finalen „Gewinner“ pro subject_id + feature_id, indem du nach Source‑Priorität sortierst und dann nach dem neuesten starts_at.
Konkretes Szenario: Kunde downgrades heute, hat aber ein Add‑on gekauft, das bis Monatsende gilt. Mit starts_at/ends_at in Entitlements wirkt der Downgrade sofort für planbasierte Features, während das Add‑on bis zum ends_at aktiv bleibt. Deine App beantwortet „dürfen sie?“ mit einer einzigen Abfrage statt mit Speziallogik.
Subscriptions, Items und zeitlich begrenzter Zugriff
Dein Produktkatalog (Pläne, Add‑ons, Features) ist das „Was“. Subscriptions sind das „Wer hat was und wann“. Wenn du das trennst, werden Upgrades und Kündigungen überschaubar.
Ein praktisches Pattern: eine Subscription pro Account, und viele Subscription‑Items darunter (ein Basisplan‑Item plus null oder mehr Add‑on‑Items). Das gibt dir einen sauberen Ort, Änderungen über die Zeit zu speichern, ohne Zugriffregeln umzuschreiben.
Kern‑Tabellen für die Kauf‑Timeline
Halte es einfach mit zwei leicht abfragbaren Tabellen:
- subscriptions: id, account_id, status (active, trialing, canceled, past_due), started_at, current_period_start, current_period_end, canceled_at (nullable)
- subscription_items: id, subscription_id, item_type (plan, addon), plan_id/addon_id, quantity, started_at, ends_at (nullable), source (stripe, manual, promo)
Ein gängiges Detail: speichere jedes Item mit eigenen Daten. So kannst du ein Add‑on nur für 30 Tage gewähren oder einen Plan bis zum Ende des bezahlten Zeitraums laufen lassen, selbst wenn der Kunde die Verlängerung kündigt.
Trenne Proration/Billing von Zugriffsslogik
Proration, Rechnungen und Zahlungsversuche sind Billing‑Probleme. Feature‑Zugriff ist ein Entitlement‑Problem. Versuche nicht, Zugriff aus Rechnungszeilen zu berechnen.
Lass stattdessen Billing‑Events Abonnement‑Datensätze aktualisieren (z. B. current_period_end verlängern, eine neue subscription_item‑Zeile anlegen oder ends_at setzen). Deine App beantwortet Zugriffsfragen aus der Subscription‑Timeline (und später aus der Entitlement‑Schicht), nicht aus Billing‑Mathematik.
Geplante Änderungen ohne Überraschungen
Upgrades und Downgrades treten oft zu einem bestimmten Zeitpunkt in Kraft:
- Füge
pending_plan_idundchange_atinsubscriptionshinzu für eine einzelne geplante Planänderung. - Oder nutze eine
subscription_changes‑Tabelle (subscription_id, effective_at, from_plan_id, to_plan_id, reason), wenn du Historie und mehrere künftige Änderungen brauchst.
So vermeidest du hartkodierte Regeln wie „Downgrades erfolgen am Periodenende“ verstreut im Code. Der Zeitplan ist Daten.
Wo Trials reinpassen
Trials sind einfach zeitlich begrenzte Zugriffe mit einer anderen Quelle. Zwei saubere Optionen:
- Behandle Trial als Subscription‑Status (trialing) mit trial_start/trial_end.
- Oder erstelle trial‑gewährte Items/Entitlements mit started_at/ends_at und source = trial.
Wenn du das in AppMaster baust, mappen diese Tabellen sauber in den Data Designer (PostgreSQL) und die Datumsangaben machen Abfragen „was ist jetzt aktiv“ ohne Spezialfälle einfach.
Schritt für Schritt: Pattern implementieren
Ein gutes Schema gibt ein Versprechen: Feature‑Logik lebt in Daten, nicht verstreut im Code. Deine App sollte eine Frage stellen können – „was sind die effektiven Entitlements gerade?“ – und eine klare Antwort bekommen.
1) Features mit stabilen Keys definieren
Erstelle eine feature‑Tabelle mit einem stabilen, menschenlesbaren Key, den du niemals umbenennst (auch wenn das UI‑Label sich ändert). Gute Keys sehen aus wie export_csv, api_calls_per_month oder seats.
Füge einen Typ hinzu, damit das System weiß, wie der Wert zu behandeln ist: boolean (an/aus) vs numerisch (Limits/Quoten). Halte es einfach und konsistent.
2) Pläne und Add‑ons auf Entitlements abbilden
Du brauchst zwei Wahrheiten: was ein Plan beinhaltet und was ein Add‑on gewährt.
Eine praktische Abfolge:
- Lege alle Features in eine
feature‑Tabelle mit stabilen Keys und einem value_type. - Erstelle
planundplan_entitlement, wo jede Zeile einen Feature‑Wert gewährt (z. B.seats = 5,export_csv = true). - Erstelle
addonundaddon_entitlement, die zusätzliche Werte gewähren (z. B.seats + 10,api_calls_per_month + 50000, oderpriority_support = true). - Entscheide, wie Werte kombiniert werden: Booleans meist OR, numerische Limits oft MAX (höher gewinnt), seat‑ähnliche Mengen oft SUM.
- Halte fest, wann Entitlements starten und enden, damit Upgrades, Kündigungen und Proration den Zugriff nicht beschädigen.
Wenn du AppMaster verwendest, kannst du diese Tabellen im Data Designer modellieren und die Kombinationsregeln als kleine „Policy“‑Tabelle oder Enum in deiner Business Process‑Logik ablegen.
3) „Effektive Entitlements“ erzeugen
Du hast zwei Optionen: on‑read berechnen (bei jeder Abfrage zusammenführen) oder einen gecachten Snapshot erzeugen, wenn sich etwas ändert (Planwechsel, Add‑on‑Kauf, Renewal, Kündigung). Für die meisten Apps sind Snapshots einfacher und performant.
Ein gängiger Weg ist eine account_entitlement‑Tabelle, die das finale Ergebnis pro Feature speichert, plus valid_from und valid_to.
4) Zugriff mit einer Prüfung durchsetzen
Verteile Regeln nicht über Bildschirme, Endpunkte und Hintergrundjobs. Lege eine Funktion an, die effektive Entitlements liest und entscheidet.
can(account_id, feature_key, needed_value=1):
ent = get_effective_entitlement(account_id, feature_key, now)
if ent.type == "bool": return ent.value == true
if ent.type == "number": return ent.value >= needed_value
Sobald alle Komponenten can(...) aufrufen, sind Upgrades und Add‑ons Datenupdates, keine Code‑Änderungen.
Beispiel‑Szenario: Upgrade plus Add‑on ohne Überraschungen
Ein sechsköpfiges Support‑Team ist auf dem Starter‑Plan. Starter enthält 3 Agent‑Seats und 1.000 SMS‑Nachrichten pro Monat. Mitte des Monats wachsen sie auf 6 Agents und möchten ein SMS‑Paket über 5.000 Nachrichten. Das sollte ohne Spezialcode funktionieren wie „wenn Plan = Pro dann …“.
Tag 1: Start auf Starter
Du legst eine subscription für das Konto an mit einer Abrechnungsperiode (z. B. 1. Jan bis 31. Jan). Dann fügst du ein subscription_item für den Plan hinzu.
Beim Checkout (oder per Nachtjob) schreibst du Entitlement‑Zuschüsse für diesen Zeitraum:
entitlement_grant:agent_seats, Wert3, StartJan 1, EndeJan 31entitlement_grant:sms_messages, Wert1000, StartJan 1, EndeJan 31
Deine App fragt nie „welchen Plan haben sie?“. Sie fragt „wie ist ihr effektives Entitlement gerade?“ und bekommt seats = 3, SMS = 1000.
Tag 15: Upgrade auf Pro, am selben Tag SMS‑Paket
Am 15. Jan upgraden sie auf Pro (enthält 10 Agent‑Seats und 2.000 SMS). Du änderst alte Grants nicht. Du fügst neue Datensätze hinzu:
- Schließe das alte Plan‑Item: setze
subscription_item(Starter) end aufJan 15 - Erstelle ein neues Plan‑Item:
subscription_item(Pro) startJan 15, endJan 31 - Füge ein neues Add‑on‑Item hinzu:
subscription_item(SMS Pack 5000) startJan 15, endJan 31
Dann werden Grants für denselben Zeitraum ergänzt:
entitlement_grant:agent_seats, Wert10, StartJan 15, EndeJan 31entitlement_grant:sms_messages, Wert2000, StartJan 15, EndeJan 31entitlement_grant:sms_messages, Wert5000, StartJan 15, EndeJan 31
Was passiert sofort am 15. Jan?
- Seats: Effektive Seats werden 10 (du wählst eine Regel wie „MAX für Seats“). Sie können an diesem Tag 3 weitere Agents hinzufügen.
- SMS: Effektive SMS werden 7.000 für den Rest der Periode (du wählst „additive SUM für Message‑Packs").
Keine bestehende Nutzung muss „verschoben“ werden. Deine Usage‑Tabelle zählt weiter; die Entitlement‑Prüfung vergleicht nur die Nutzung dieser Periode mit dem aktuellen effektiven Limit.
Tag 25: Downgrade geplant, Zugriff bis Periodenende behalten
Am 25. Jan planen sie ein Downgrade zurück zu Starter ab 1. Feb. Du änderst die Grants für Januar nicht. Du erstellst zukünftige Items (oder künftige Grants) für die nächste Periode:
subscription_item(Starter) startFeb 1, endFeb 28- Kein SMS‑Pack‑Item ab
Feb 1
Ergebnis: Sie behalten Pro‑Seats und das SMS‑Pack bis zum 31. Jan. Am 1. Feb sinken die Seats auf 3 und die SMS‑Limits gelten für die neue Periode. Das ist einfach nachvollziehbar und lässt sich in einem No‑Code‑Workflow in AppMaster sauber abbilden: Datumsänderungen erzeugen neue Zeilen, und die Entitlement‑Abfrage bleibt unangetastet.
Häufige Fehler und Fallen
Die meisten Subscription‑Bugs sind keine Billing‑Bugs. Es sind Zugriffs‑Bugs, verursacht durch verstreute Logik. Der schnellste Weg, ein Schema zu brechen, ist die Frage „dürfen sie das?“ an fünf verschiedenen Stellen zu beantworten.
Ein klassisches Scheitern ist, Regeln hartkodiert im UI, der API und in Hintergrundjobs zu verteilen. Das UI versteckt einen Button, die API blockiert den Endpoint nicht, und ein Nachträglich‑Job läuft weiter, weil er etwas Anderes prüft. Du bekommst schwer reproduzierbare „es funktioniert manchmal“‑Berichte.
Eine andere Falle ist, plan_id‑Checks statt Feature‑Checks zu benutzen. Das wirkt anfangs simpel („Plan A kann exportieren, Plan B nicht“), fällt aber auseinander, sobald ein Add‑on, ein grandfathered Kunde, ein Trial oder ein Enterprise‑Ausnahmefall auftaucht. Wenn du jemals sagst „if plan is Pro then allow…“, baust du ein Labyrinth, das du ewig pflegen musst.
Zeit‑ und Kündigungsedgecases
Zugriff „bleibt auch hängen“, wenn du nur ein Boolean wie has_export = true speicherst und nie Daten zum Zeitraum anhängst. Kündigungen, Rückerstattungen, Chargebacks und Mid‑Cycle‑Downgrades brauchen Zeitangaben. Ohne starts_at und ends_at gewährst du versehentlich dauerhaften Zugriff oder nimmst ihn zu früh weg.
Eine einfache Regel, um das zu vermeiden:
- Jeder Entitlement‑Grant muss eine Quelle (plan, add‑on, manuelle Override) und einen Zeitraum haben.
- Jede Zugriffentscheidung sollte „now zwischen start und end“ verwenden (mit klaren Regeln für null end‑Dates).
- Hintergrundjobs sollten Entitlements zur Laufzeit neu prüfen, nicht den gestrigen Zustand voraussetzen.
Mische nicht Billing und Zugriff
Teams geraten auch in Probleme, wenn Billing‑Datensätze und Zugriffregeln in derselben Tabelle landen. Billing braucht Rechnungen, Steuern, Proration, Provider‑IDs und Retry‑States. Zugriff braucht klare Feature‑Keys und Zeitfenster. Wenn beides verwoben ist, wird eine Billing‑Migration schnell zum Produkt‑Ausfall.
Zum Schluss: Viele Systeme überspringen die Audit‑Spur. Wenn ein Nutzer fragt „warum kann ich exportieren?“, brauchst du eine Antwort wie: „Aktiviert durch Add‑on X vom 2026‑01‑01 bis 2026‑02‑01“ oder „Manuell gewährt durch Support, Ticket 1842.“ Ohne das raten Support und Engineering.
Wenn du das in AppMaster baust, halte Audit‑Felder in deinem Data Designer Modell und mache die „dürfen sie?“‑Prüfung zu einem einzigen Business Process, der Web, Mobile und geplante Abläufe nutzt.
Schnelle Checkliste vor dem Go‑Live
Bevor du dein Schema live schaltest, mache einen letzten Durchlauf mit realen Fragen, nicht Theorie. Das Ziel: Zugriff ist erklärbar, testbar und änderungsfreundlich.
Reality‑Check Fragen
Wähle einen Nutzer und ein Feature und erkläre das Ergebnis so, wie du es Support oder Finanzen erklären würdest. Wenn deine Antwort nur „sie sind auf Pro“ ist (oder schlimmer: „der Code sagt das“), passiert dir Schmerz beim ersten Mid‑Cycle‑Upgrade oder einem Einmal‑Deal.
Nutze diese Checkliste:
- Kannst du „warum hat dieser Nutzer Zugriff?“ allein mit Daten beantworten (Subscription‑Items, Add‑ons, Overrides und Zeitfenster), ohne Application‑Code zu lesen?
- Basieren alle Zugriffprüfungen auf stabilen Feature‑Keys (wie
feature.export_csv) statt auf Plan‑Namen (wie „Starter“ oder „Business“)? Plan‑Namen ändern sich; Feature‑Keys sollten das nicht. - Haben Entitlements klare Start‑ und Endzeiten, inklusive Trials, Grace‑Periods und geplanter Kündigungen? Wenn Zeit fehlt, werden Downgrades Streitpunkte.
- Kannst du einem Kunden mittels eines Override‑Records für einen Monat 10 zusätzliche Seats geben, ohne Logik zu verzweigen? So behandelst du „gib ihnen diesen Monat 10 extra Seats“ ohne Custom‑Code.
- Kannst du ein Upgrade und ein Downgrade mit wenigen Beispiel‑Zeilen testen und vorhersehbare Ergebnisse bekommen? Wenn du ein komplexes Skript brauchst, ist dein Modell zu implizit.
Ein praktischer Test: Erstelle drei Nutzer (neu, mid‑month upgraded, gekündigt) und ein Add‑on (z. B. „extra seats“ oder „erweiterte Berichte“). Führe deine Zugriffsabfrage für jeden aus. Wenn die Resultate offensichtlich und erklärbar sind, bist du bereit.
Wenn du ein Tool wie AppMaster nutzt, gilt dieselbe Regel: mache eine Stelle (eine Abfrage oder ein Business Process) verantwortlich für „dürfen sie?“, sodass alle Web‑ und Mobile‑Screens dieselbe Antwort nutzen.
Nächste Schritte: Upgrades wartbar machen
Am besten hältst du Upgrades stabil, indem du kleiner startest als gedacht. Wähle eine Handvoll Features, die tatsächlich Wert treiben (5–10 reichen), und baue eine Entitlement‑Prüfung, die eine einzige Frage beantwortet: „Kann dieses Konto X gerade?“ Wenn du das nicht an einer Stelle beantworten kannst, bleiben Upgrades riskant.
Wenn diese eine Prüfung funktioniert, behandle Upgrade‑Pfade als Produktverhalten, nicht nur als Billing‑Verhalten. Der schnellste Weg, seltsame Randfälle zu finden, ist ein kleines Set an Zugriffstests basierend auf realen Kundenbewegungen.
Praktische nächste Schritte mit direktem Nutzen:
- Definiere einen minimalen Feature‑Katalog und mappe jeden Plan auf klare Entitlements.
- Füge Add‑ons als separate Items hinzu, die Entitlements gewähren oder verlängern, statt sie in Plan‑Regeln einzubetten.
- Schreibe 5–10 Zugriffstests für gängige Pfade (mid‑cycle Upgrade, Downgrade bei Verlängerung, Add‑on hinzufügen/entfernen, Trial→Paid, Grace‑Period).
- Mach Preisänderungen datenbasiert: Update Plan‑Zeilen, Feature‑Mappings und Entitlement‑Grants, nicht Applikationscode.
- Gewöhne dir an: Jeder neue Plan oder Add‑on braucht mindestens einen Test, der zeigt, dass Zugriff wie erwartet funktioniert.
Selbst in einem No‑Code‑Backend lässt sich dieses Pattern sauber modellieren. In AppMaster passt der Data Designer gut zum Aufbau der Kern‑Tabellen (plans, features, subscriptions, subscription_items, entitlements). Der Business Process Editor kann den Zugriffentscheidungsfluss halten (aktive Entitlements laden, Zeitfenster anwenden, Allow/Deny zurückgeben), sodass du keine verstreuten Prüf‑Routinen in Endpunkten händisch pflegen musst.
Die Belohnung zeigt sich beim nächsten Pricing‑Change. Statt Regeln umzuschreiben, änderst du Daten: Ein Feature wandert von „Pro“ zu einem Add‑on, ein Entitlement‑Zeitraum ändert sich oder ein Legacy‑Plan behält alte Grants. Deine Zugriffslogik bleibt stabil, und Upgrades werden zu kontrollierten Datenupdates statt zu Code‑Sprints.
Wenn du dein Schema schnell validieren willst, modellier ein Upgrade plus ein Add‑on End‑to‑End und führe die Zugriffstests durch, bevor du weiteres hinzufügst.


