Schema del database per piani e entitlements per upgrade e add-on
Schema di database per piani e entitlements che supporta upgrade, add-on, trial e revoche senza regole hardcoded, usando tabelle chiare e controlli temporali.

Perché piani e funzionalità diventano rapidamente complicati
I piani sembrano semplici su una pagina prezzi: Basic, Pro, Enterprise. Il caos inizia nel momento in cui cerchi di trasformare quei nomi in regole di accesso reali dentro la tua app.
Hardcodare i controlli delle feature (come if plan = Pro then allow X) funziona per la prima versione. Poi i prezzi cambiano. Una funzionalità passa da Pro a Basic, compare un nuovo add-on o un'offerta commerciale include un bundle personalizzato. Improvvisamente hai la stessa regola copiata tra API, UI, app mobile e job in background. Modifichi un posto e te ne dimentichi un altro. Gli utenti se ne accorgono.
Un secondo problema è il tempo. Le sottoscrizioni non sono un'etichetta statica; cambiano a metà ciclo. Qualcuno fa l'upgrade oggi, downgrade il mese successivo, mette in pausa o cancella lasciando tempo pagato residuo. Se il tuo database memorizza solo il “piano corrente”, perdi la cronologia e non puoi rispondere a domande basilari in seguito: cosa potevano fare lo scorso martedì? Perché l'assistenza ha approvato un rimborso?
Gli add-on peggiorano la situazione perché si applicano trasversalmente ai piani. Un add-on può sbloccare posti aggiuntivi, rimuovere un limite o abilitare una funzione specifica. Le persone possono comprarlo su qualsiasi piano, rimuoverlo dopo o mantenerlo dopo un downgrade. Se la regola è incorporata nel codice, ti ritrovi con una pila crescente di casi speciali.
Ecco le situazioni che di solito mandano in crisi i design ingenui:
- Upgrade a metà ciclo: l'accesso dovrebbe cambiare immediatamente, la prorata di fatturazione può seguire regole diverse.
- Downgrade programmato: l'accesso può rimanere "più alto" fino alla fine del periodo pagato.
- Grandfathering: clienti vecchi conservano una funzione che i nuovi non ricevono.
- Offerte personalizzate: un account ottiene la Funzione A ma non la Funzione B, pur condividendo lo stesso nome di piano.
- Esigenze di audit: supporto, finanza o compliance chiedono "cosa era esattamente abilitato e quando?"
L'obiettivo è semplice: un modello di controllo accessi flessibile che si adatti ai cambiamenti di prezzo, senza riscrivere la logica di business ogni volta. Vuoi un solo posto dove chiedere "possono farlo?" e una traccia nel database che spieghi la risposta.
Alla fine di questo articolo avrai un pattern di schema che puoi copiare: piani e add-on diventano input, e gli entitlements diventano la singola fonte di verità per l'accesso alle funzionalità. Lo stesso approccio si adatta anche a builder no-code come AppMaster, perché puoi mantenere le regole nei dati e interrogarle in modo coerente dal backend, dal web e dalle app mobile.
Termini chiave: piano, add-on, entitlement e accesso
Molti problemi di sottoscrizione nascono da un problema di vocabolario. Se tutti usano la stessa parola per significare cose diverse, il tuo schema si trasforma in casi speciali.
Qui i termini da mantenere separati in uno schema piani e entitlements:
- Plan: il bundle predefinito che qualcuno ottiene quando si abbona (per esempio Basic o Pro). Un piano di solito fissa i limiti di base e le funzionalità incluse.
- Add-on: un acquisto opzionale che modifica il baseline (per esempio “posti extra” o “reportistica avanzata”). Gli add-on dovrebbero poter essere aggiunti e rimossi senza cambiare il piano.
- Entitlement: il risultato finale e calcolato di "cosa hanno in questo momento", dopo aver combinato piano + add-on + override. È a questo che la tua app dovrebbe interrogare.
- Permission (o capability): un'azione specifica che qualcuno può compiere (per esempio "esporta dati" o "gestisci fatturazione"). Le permission spesso dipendono dal ruolo oltre che dagli entitlements.
- Access: l'esito reale quando l'app applica le regole (la schermata mostra o nasconde una funzione, una chiamata API è autorizzata o bloccata, si applica un limite).
I feature flag sono correlati ma diversi. Un feature flag è tipicamente un interruttore di prodotto che controlli (rollout, esperimenti, disattivare una funzione durante un incidente). Un entitlement è l'accesso specifico del cliente basato su ciò per cui paga o su ciò che gli hai concesso. Usa i flag quando vuoi cambiare comportamento per gruppi senza toccare la fatturazione. Usa gli entitlements quando l'accesso deve corrispondere a una sottoscrizione, una fattura o un contratto.
Lo scope è un'altra fonte di confusione. Mantieni chiare queste idee:
- User: una persona. Utile per ruoli (admin vs membro) e limiti personali.
- Account (cliente): l'entità che paga. Utile per le informazioni di fatturazione e la proprietà della sottoscrizione.
- Workspace (progetto/team): dove avviene il lavoro. Molti prodotti applicano entitlements qui (posti, storage, moduli abilitati).
Il tempo conta perché l'accesso cambia. Modellalo direttamente:
- Inizio e fine: un entitlement può essere attivo solo in una finestra temporale (trial, promo, contratto annuale).
- Cambio pianificato: gli upgrade possono iniziare ora; i downgrade spesso iniziano al prossimo rinnovo.
- Grace e cancellazione: puoi permettere accesso limitato dopo un fallimento di pagamento, ma solo fino a una data di fine chiara.
Esempio: un'azienda è su Pro, aggiunge "Reportistica Avanzata" a metà mese, poi programma un downgrade a Basic nel ciclo successivo. Il piano cambia più tardi, l'add-on parte subito, e lo strato degli entitlements rimane il singolo posto dove chiedere: "Questo workspace può usare i report avanzati oggi?"
Uno schema core semplice per piani e funzionalità
Un buon schema piani e entitlements parte piccolo: separa ciò che vendi (piani e add-on) da ciò che le persone possono fare (feature). Se mantieni nette queste due idee, upgrade e nuovi add-on diventano modifiche ai dati, non riscritture.
Ecco un set pratico di tabelle che funziona per la maggior parte dei prodotti in abbonamento:
- products: la cosa vendibile (piano base, piano Team, add-on posti extra, add-on supporto prioritario).
- plans: opzionale, se vuoi che i piani siano un tipo speciale di prodotto con campi solo per i piani (intervallo di fatturazione, ordine pubblico di visualizzazione). Molti team conservano i piani dentro
productse usano una colonnaproduct_type. - features: il catalogo delle capacità (accesso API, max progetti, esportazione, SSO, crediti SMS).
- product_features (o
plan_featuresse separi i piani): una tabella di join che dice quali feature sono incluse in quale prodotto, di solito con un valore.
Quella tabella di join è dove risiede gran parte della potenza. Le feature raramente sono solo on/off. Un piano potrebbe includere max_projects = 10, mentre un add-on potrebbe aggiungere +5. Quindi product_features dovrebbe supportare almeno:
feature_value(numero, testo, JSON o colonne separate)value_type(boolean, integer, enum, json)grant_mode(replace vs add), così un add-on può "aggiungere 5 posti" invece di sovrascrivere un limite base
Modella gli add-on come prodotti a loro volta. L'unica differenza è come vengono acquistati. Un prodotto piano di base è "uno alla volta", mentre un add-on potrebbe permettere quantità. Ma entrambi mappano alle feature allo stesso modo. Questo evita casi speciali come "se add-on X allora abilita Y" sparsi nel codice.
Le feature dovrebbero essere dati, non costanti nel codice. Se hardcoding dei controlli delle feature avviene in più servizi, alla fine distribuirai discrepanze (web dice sì, mobile dice no, backend non è d'accordo). Quando le feature vivono nel database, l'app può fare una domanda coerente e puoi distribuire cambiamenti modificando righe.
La nomenclatura conta più di quanto si pensi. Usa identificatori stabili che non cambino mai, anche se il nome marketing cambia:
feature_keycomemax_projects,sso,priority_supportproduct_codecomeplan_starter_monthly,addon_extra_seats
Tieni le etichette di visualizzazione separate (feature_name, product_name). Se usi AppMaster Data Designer con PostgreSQL, trattare queste chiavi come campi unici paga subito: puoi rigenerare in sicurezza mantenendo integrazioni e report stabili.
Lo strato degli entitlements: un solo posto dove chiedere "possono?"
La maggior parte dei sistemi di sottoscrizione si complicano quando "ciò che hanno comprato" è memorizzato in un posto, ma "ciò che possono fare" viene calcolato in cinque diversi percorsi di codice. La soluzione è uno strato di entitlements: una singola tabella (o view) che rappresenta l'accesso effettivo per un soggetto in un punto nel tempo.
Se punti a uno schema piani e entitlements che sopravviva a upgrade, downgrade, trial e concessioni una tantum, questo layer è la parte che rende tutto prevedibile.
Una tabella entitlements pratica
Pensa a ogni riga come a una singola rivendicazione: "questo soggetto ha accesso a questa feature con questo valore, da questo momento a questo momento, da questa fonte." Una struttura comune appare così:
- subject_type (es.
"account","user","org") e subject_id - feature_id
- value (il valore effettivo per quella feature)
- source (da dove proviene:
"direct","plan","addon","default") - starts_at e ends_at (ends_at nullable per accessi continui)
Puoi implementare value in diversi modi: una singola colonna text/JSON più value_type, o colonne separate come value_bool, value_int, value_text. Mantienilo banale e facile da interrogare.
Tipi di valore che coprono la maggior parte dei prodotti
Le feature non sono sempre on/off. Questi tipi di valore coprono la maggior parte dei bisogni di fatturazione e controllo accesso:
- Boolean: abilitato/disabilitato (
can_export= true) - Numero di quota: un limite (
seats= 10,api_calls= 100000) - Livello di tier: un rango (
support_tier= 2) - Stringa: una modalità o variante (
data_retention=90_days)
Precedenza: come risolvere i conflitti
I conflitti sono normali. Un utente potrebbe essere su un piano che permette 5 posti, acquistare un add-on per 10 in più e ricevere anche una concessione manuale dal supporto.
Stabilisci una regola chiara e applicala ovunque:
- Il grant diretto sovrascrive il piano
- Poi gli add-on
- Poi i valori di default
Un approccio semplice è memorizzare tutte le righe candidate (derivate dal piano, dagli add-on, dirette) e calcolare il “vincitore” finale per subject_id + feature_id ordinando per precedenza della source, poi per starts_at più recente.
Ecco uno scenario concreto: un cliente fa downgrade del piano oggi, ma ha già pagato un add-on che dura fino alla fine del mese. Con starts_at/ends_at sugli entitlements, il downgrade ha effetto immediato per le feature derivate dal piano, mentre la feature dell'add-on rimane attiva fino al suo ends_at. La tua app può rispondere "possono?" con una sola query invece di logiche di casi speciali.
Sottoscrizioni, item e accesso vincolato nel tempo
Il tuo catalogo piani (piani, add-on, feature) è il "cosa". Le sottoscrizioni sono il "chi ha cosa, e quando". Se separi questi concetti, upgrade e cancellazioni smettono di essere spaventosi.
Un pattern pratico è: una sottoscrizione per account, e molti subscription items sotto di essa (uno per il piano base, più zero o più add-on). In uno schema piani e entitlements, questo ti dà un posto pulito per registrare i cambiamenti nel tempo senza riscrivere le regole di accesso.
Tabelle core per modellare la timeline d'acquisto
Puoi mantenerlo semplice con due tabelle facili da interrogare:
- 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)
Un dettaglio comune: memorizza ogni item con le sue date. In questo modo puoi concedere un add-on solo per 30 giorni, o lasciare che un piano continui fino alla fine di un periodo pagato anche se il cliente cancella il rinnovo.
Tieni la prorata e la fatturazione fuori dalla logica di accesso
Prorata, fatture e tentativi di pagamento sono problemi di fatturazione. L'accesso alle feature è un problema di entitlement. Non cercare di "calcolare l'accesso" dalle righe di fattura.
Invece, lascia che gli eventi di fatturazione aggiornino i record di sottoscrizione (per esempio estendere current_period_end, creare una nuova riga subscription_item o impostare ends_at). La tua app risponde alle domande di accesso dalla timeline della sottoscrizione (e successivamente dallo strato entitlement), non dalla matematica della fatturazione.
Cambiamenti programmati senza sorprese
Upgrade e downgrade spesso prendono effetto in un momento specifico:
- Aggiungi
pending_plan_idechange_atsulle subscriptions per un singolo cambiamento di piano programmato. - Oppure usa una tabella
subscription_changes(subscription_id, effective_at, from_plan_id, to_plan_id, reason) se ti serve storico e più cambiamenti futuri.
Questo evita di hardcodare regole come "i downgrade avvengono a fine periodo" in parti casuali del codice. La pianificazione è dato.
Dove si inseriscono i trial
I trial sono semplicemente accessi limitati nel tempo con una fonte diversa. Due opzioni pulite:
- Tratta il trial come uno status di sottoscrizione (trialing) con trial_start/trial_end.
- Oppure crea item/entitlements concessi per il trial con started_at/ends_at e source = trial.
Se stai costruendo questo in AppMaster, queste tabelle si mappano bene al Data Designer in PostgreSQL, e le date rendono semplice interrogare "cosa è attivo adesso" senza casi speciali.
Passo dopo passo: implementare il pattern
Un buon schema piani e entitlements inizia con una promessa: la logica sulle feature vive nei dati, non sparsa nei percorsi di codice. La tua app dovrebbe fare una domanda sola - "quali sono gli entitlements effettivi adesso?" - e ottenere una risposta chiara.
1) Definisci le feature con chiavi stabili
Crea una tabella feature con una chiave stabile e leggibile che non rinominerai mai (anche se l'etichetta UI cambia). Chiavi valide sono export_csv, api_calls_per_month o seats.
Aggiungi un tipo in modo che il sistema sappia come trattare il valore: boolean (on/off) vs numerico (limiti/quote). Mantienilo semplice e coerente.
2) Mappa piani e add-on agli entitlements
Ora ti servono due fonti di verità: ciò che un piano include e ciò che ogni add-on concede.
Una sequenza semplice e pratica è:
- Metti tutte le feature in una tabella
featurecon chiavi stabili e un tipo di valore. - Crea
planeplan_entitlementdove ogni riga concede un valore di feature (per esempioseats = 5,export_csv = true). - Crea
addoneaddon_entitlementche concedono valori extra (per esempioseats + 10,api_calls_per_month + 50000, opriority_support = true). - Decidi come combinare i valori: i boolean fanno solitamente OR, i limiti numerici spesso usano MAX (vince il valore più alto) e le quantità come i posti spesso usano SUM.
- Registra quando gli entitlements iniziano e finiscono così upgrade, cancellazioni e prorate non rompono i controlli di accesso.
Se costruisci questo in AppMaster, puoi modellare queste tabelle nel Data Designer (PostgreSQL) e mantenere le regole di combinazione come una piccola tabella "policy" o enum usata dalla tua Business Process logic.
3) Produci gli "entitlements effettivi"
Hai due opzioni: calcolare al momento della lettura (query e merge ogni volta) o generare uno snapshot memorizzato quando qualcosa cambia (cambio piano, acquisto add-on, rinnovo, cancellazione). Per la maggior parte delle app, gli snapshot sono più semplici da ragionare e più veloci sotto carico.
Un approccio comune è una tabella account_entitlement che memorizza il risultato finale per feature, più valid_from e valid_to.
4) Applica l'accesso con un unico controllo
Non diffondere le regole tra schermate, endpoint e job background. Metti una funzione nell'app che legga gli entitlements effettivi e decida.
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
Una volta che tutto chiama can(...), upgrade e add-on diventano aggiornamenti di dati, non riscritture.
Scenario d'esempio: upgrade più add-on senza sorprese
Un team di supporto di 6 persone è sul piano Starter. Starter include 3 posti agent e 1.000 SMS al mese. A metà mese crescono a 6 agenti e vogliono un pacchetto SMS extra da 5.000. Vuoi che questo funzioni senza codice di caso speciale come "se piano = Pro allora...".
Giorno 1: partono su Starter
Crei una subscription per l'account con un periodo di fatturazione (per esempio 1 Gen - 31 Gen). Poi aggiungi un subscription_item per il piano.
Al checkout (o tramite un job notturno), scrivi concessioni di entitlement per quel periodo:
entitlement_grant:agent_seats, valore3, start1 Gen, end31 Genentitlement_grant:sms_messages, valore1000, start1 Gen, end31 Gen
La tua app non chiede mai "su quale piano sono?". Chiede "qual è il loro entitlement effettivo adesso?" e riceve seats = 3, SMS = 1000.
Giorno 15: upgrade a Pro, nello stesso giorno aggiungono il pacchetto SMS
Il 15 Gen fanno l'upgrade a Pro (include 10 posti agent e 2.000 SMS). Non modifichi i grant precedenti. Aggiungi nuove righe:
- Chiudi il vecchio item di piano: imposta
subscription_item(Starter) end a15 Gen - Crea un nuovo item di piano:
subscription_item(Pro) start15 Gen, end31 Gen - Aggiungi un nuovo item add-on:
subscription_item(SMS Pack 5000) start15 Gen, end31 Gen
Poi i grant per lo stesso periodo vengono aggiunti:
entitlement_grant:agent_seats, valore10, start15 Gen, end31 Genentitlement_grant:sms_messages, valore2000, start15 Gen, end31 Genentitlement_grant:sms_messages, valore5000, start15 Gen, end31 Gen
Cosa succede immediatamente il 15 Gen?
- Posti: i posti effettivi diventano 10 (scegli una regola come "prendi il max per i posti"). Possono aggiungere 3 agenti in più quel giorno.
- SMS: gli SMS effettivi diventano 7.000 per il resto del periodo (scegli "somma per i pacchetti messaggi").
Nessun utilizzo esistente deve essere "spostato." La tua tabella di utilizzo continua a contare i messaggi inviati; il controllo dell'entitlement semplicemente confronta l'utilizzo di questo periodo con il limite effettivo corrente.
Giorno 25: programmare un downgrade, mantenere l'accesso fino alla fine del periodo
Il 25 Gen programmano un downgrade a Starter a partire dal 1 Feb. Non tocchi i grant di Gen. Crei item futuri (o grant futuri) per il periodo successivo:
subscription_item(Starter) start1 Feb, end28 Feb- Nessun item SMS pack che inizi il 1 Feb
Risultato: mantengono i posti Pro e il pacchetto SMS fino al 31 Gen. Il 1 Feb, i posti effettivi scendono a 3 e gli SMS tornano ai limiti Starter per il nuovo periodo. Questo è facile da ragionare e si mappa pulitamente a un workflow no-code in AppMaster: cambiare le date crea nuove righe e la query degli entitlements rimane la stessa.
Errori comuni e trappole
La maggior parte dei bug di sottoscrizione non sono bug di fatturazione. Sono bug di accesso causati da logica sparsa nel prodotto. Il modo più rapido per rompere uno schema piani e entitlements è rispondere "possono usare questo?" in cinque posti diversi.
Un fallimento classico è hardcodare regole nell'UI, nell'API e nei job background separatamente. L'UI nasconde un pulsante, l'API dimentica di bloccare l'endpoint e un job notturno continua a funzionare perché controlla qualcos'altro. Ti ritrovi con segnalazioni confuse del tipo "funziona a volte" difficili da riprodurre.
Un'altra trappola è usare controlli su plan_id invece di controlli basati sulle feature. All'inizio sembra semplice (Piano A può esportare, Piano B no), ma crolla quando aggiungi un add-on, un cliente grandfathered, una prova gratuita o un'eccezione enterprise. Se dici mai "if plan is Pro then allow...", stai costruendo un labirinto che dovrai mantenere per sempre.
Casi limite di tempo e cancellazione
L'accesso si "incastra" anche quando memorizzi solo un booleano come has_export = true e non alleghi mai date. Cancellazioni, rimborsi, chargeback e downgrade a metà ciclo hanno tutti bisogno di limiti temporali. Senza starts_at e ends_at, concederai accesso permanente per errore o toglierai accesso troppo presto.
Un controllo semplice per evitare questo è:
- Ogni entitlement grant deve avere una source (piano, add-on, override manuale) e un intervallo di tempo.
- Ogni decisione di accesso dovrebbe usare "now tra start e end" (con regole chiare per end null).
- I job background dovrebbero rivedere gli entitlements al momento dell'esecuzione, non assumere lo stato di ieri.
Non mescolare fatturazione e accesso
I team si mettono nei guai anche mescolando record di fatturazione e regole di accesso nella stessa tabella. La fatturazione necessita di fatture, tasse, prorate, provider IDs e stati di retry. L'accesso necessita di chiavi di feature chiare e finestre temporali. Quando sono intrecciati, una migrazione di fatturazione diventa un outage del prodotto.
Infine, molti sistemi saltano una traccia di audit. Quando un utente chiede "perché posso esportare?", hai bisogno di una risposta come: "Abilitato dall'Add-on X dal 2026-01-01 al 2026-02-01" o "Concesso manualmente dall'assistenza, ticket 1842." Senza questo, supporto e engineering indovinano.
Se costruisci questo in AppMaster, tieni i campi di audit nel tuo modello Data Designer e rendi il controllo "possono?" un singolo Business Process usato da web, mobile e flussi schedulati.
Checklist rapida prima della pubblicazione
Prima di mettere in produzione il tuo schema piani e entitlements, fai un'ultima verifica con domande reali, non teoria. L'obiettivo è che l'accesso sia spiegabile, testabile e modificabile facilmente.
Domande di reality check
Scegli un utente e una feature, poi cerca di spiegare il risultato come lo faresti a supporto o finanza. Se puoi rispondere solo "sono su Pro" (o peggio, "il codice lo dice"), proverai dolore la prima volta che qualcuno fa un upgrade a metà ciclo o ottiene un accordo one-off.
Usa questa checklist rapida:
- Riesci a rispondere "perché questo utente ha accesso?" usando solo i dati (subscription items, add-on, override e finestre temporali), senza leggere codice applicativo?
- Tutti i controlli di accesso sono basati su chiavi di feature stabili (come
feature.export_csv) piuttosto che su nomi di piano (come "Starter" o "Business"). I nomi dei piani cambiano; le chiavi delle feature non dovrebbero. - Gli entitlements hanno chiari tempi di inizio e fine, inclusi trial, periodi di tolleranza e cancellazioni programmate. Se manca il tempo, i downgrade diventano motivo di discussione.
- Puoi concedere o rimuovere accesso a un singolo cliente usando un record di override, senza ramificare la logica. Questo è come gestire "dare 10 posti extra questo mese" senza codice personalizzato.
- Puoi testare un upgrade e un downgrade con poche righe di esempio e ottenere risultati prevedibili. Se ti serve uno script complesso per simularlo, il tuo modello è troppo implicito.
Un test pratico: crea tre utenti (nuovo, upgraded mid-month, cancellato) e un add-on (come "posti extra" o "report avanzati"). Poi esegui la query di accesso per ciascuno. Se i risultati sono ovvi e spiegabili, sei pronto.
Se usi uno strumento come AppMaster, mantieni la stessa regola: assegna un solo posto (una query o un Business Process) responsabile per "possono?" in modo che ogni schermo web e mobile usi la stessa risposta.
Prossimi passi: rendere gli upgrade facili da mantenere
Il modo migliore per mantenere gli upgrade sotto controllo è partire più piccolo di quanto pensi. Scegli una manciata di feature che guidano davvero il valore (5-10 sono sufficienti) e costruisci un controllo di entitlement che risponda a una sola domanda: "Questo account può fare X adesso?" Se non riesci a rispondere in un solo posto, gli upgrade saranno sempre rischiosi.
Una volta che quel controllo funziona, tratta i percorsi di upgrade come comportamento di prodotto, non solo come comportamento di fatturazione. Il modo più rapido per individuare casi limite strani è scrivere un piccolo set di test di accesso basati su movimenti reali dei clienti.
Ecco passi pratici che spesso ripagano subito:
- Definisci un catalogo di feature minimo e mappa ogni piano a un set chiaro di entitlements.
- Aggiungi gli add-on come "item" separati che concedono o estendono entitlements, invece di includerli nelle regole del piano.
- Scrivi 5-10 test di accesso per percorsi comuni (upgrade a metà ciclo, downgrade al rinnovo, add-on aggiunto poi rimosso, trial a pagato, periodo di grazia).
- Rendi i cambi di prezzo solo dati: aggiorna righe piano, mapping delle feature e grant di entitlements, non il codice applicativo.
- Prendi l'abitudine: ogni nuovo piano o add-on deve avere almeno un nuovo test che dimostri che l'accesso si comporta come previsto.
Se usi un backend no-code, puoi comunque modellare questo pattern pulito. In AppMaster, il Data Designer è adatto per costruire le tabelle core (piani, feature, subscriptions, subscription items, entitlements). Poi il Business Process Editor può contenere il flusso decisionale di accesso (carica entitlements attivi, applica finestre temporali, ritorna allow/deny) così non stai scrivendo controlli sparsi negli endpoint.
Il beneficio si vede la prossima volta che cambi i prezzi. Invece di riscrivere regole, modifichi dati: una feature si sposta da "Pro" a un add-on, la durata di un entitlement cambia o un piano legacy mantiene i suoi vecchi grant. La tua logica di accesso resta stabile e gli upgrade diventano un aggiornamento controllato, non uno sprint di codice.
Se vuoi convalidare il tuo schema rapidamente, prova a modellare un upgrade e un add-on end-to-end, poi esegui quei test di accesso prima di aggiungere altro.


