Costruire SaaS Multi-Tenant: Workspace, Ruoli, Fatturazione e Isolamento
Come progettare workspace, accesso basato sui ruoli, piani di fatturazione e isolamento dei tenant per SaaS scalabile. Architettura pratica da DigiForge.

Il SaaS multi-tenant è l'architettura predefinita per qualsiasi piattaforma B2B che punti a crescere oltre una manciata di clienti. Tuttavia, il diavolo si nasconde nei dettagli: il modo in cui modelli gli spazi di lavoro, assegni i ruoli, strutturi la fatturazione e isoli i tenant determina se la tua piattaforma scalerà senza intoppi o collasserà sotto la complessità. In DigiForge, abbiamo costruito e ricostruito questi sistemi in dozzine di prodotti SaaS. Ecco cosa abbiamo imparato.
Spazi di lavoro: l'unità organizzativa principale
Uno spazio di lavoro è un contenitore logico che raggruppa utenti, dati e configurazione per un singolo cliente (o un team all'interno di un cliente). Abbiamo visto team confondere gli spazi di lavoro con gli account di fatturazione o addirittura con i progetti: non fatelo. Mantieni lo spazio di lavoro come ambito tenant fondamentale e sovrapponi altri concetti sopra.
Decisioni di progettazione chiave:
- Gerarchico o piatto? Alcune piattaforme necessitano di spazi di lavoro all'interno di spazi di lavoro (ad esempio, un'azienda con più dipartimenti). Raccomandiamo una gerarchia a due livelli: organizzazione (entità di fatturazione) e spazio di lavoro (unità di team). Evita annidamenti più profondi se non assolutamente necessario: complicano l'ereditarietà dei ruoli e l'accesso ai dati.
- Identificatori univoci: Usa uno slug leggibile (come
acmeoacme-marketing) per lo spazio di lavoro negli URL, ma affidati sempre a un UUID internamente. Gli slug possono cambiare; gli UUID no. - Soft-delete con periodo di grazia: Eliminare uno spazio di lavoro è un'azione drastica. Implementa un soft-delete di 30 giorni in modo che gli utenti possano recuperare i dati. Interrompi immediatamente la fatturazione ma conserva i dati fino alla scadenza del periodo di grazia.
Quando un nuovo utente si registra, considera il flusso di onboarding. Dovrebbe creare prima un workspace o può esplorare una sandbox? Preferiamo un flusso guidato in cui l'utente crea un'organizzazione, poi il suo primo workspace, e subito viene invitato a invitare i compagni di team. Questo riduce l'attrito e stabilisce l'aspettativa che la piattaforma è collaborativa.
Un errore comune è associare i piani di fatturazione direttamente ai workspace. Invece, associa la fatturazione a un'organizzazione che contiene uno o più workspace. Questo permette alle aziende di avere una singola fattura mentre ogni team ha il proprio workspace.
Ruoli e Permessi: Granulari, ma non troppo
Il controllo degli accessi basato sui ruoli (RBAC) è lo standard del settore, ma la granularità è importante. In DigiForge, di solito iniziamo con tre ruoli predefiniti—Admin, Membro, Visualizzatore—e permettiamo ruoli personalizzati per piani avanzati. Il ruolo Admin ha il controllo completo del workspace, i Membri possono creare e modificare la maggior parte delle risorse, e i Visualizzatori possono solo leggere.
Dove le cose si complicano è l'ambito dei permessi. I permessi dovrebbero essere limitati al workspace per impostazione predefinita, ma potresti aver bisogno di permessi a livello di organizzazione (es. gestire la fatturazione) o anche di accesso in lettura tra workspace per reportistica consolidata. Modella i permessi come un insieme di coppie azione:risorsa e assegnali ai ruoli. Memorizza le assegnazioni in una tabella di join: (workspace_id, user_id, role_id).
Consiglio da professionista: Evita di controllare le autorizzazioni solo a livello applicativo. Sposta quanta più logica di autorizzazione possibile nel database utilizzando la sicurezza a livello di riga (RLS) o un motore di policy come OPA. Questo riduce la probabilità che un bug nel livello web esponga i dati di qualcun altro.
Un pattern che ci ha dato buoni risultati è memorizzare nella cache il ruolo dell'utente all'interno di un token di sessione (JWT) invece di interrogare il database a ogni richiesta. Ma attenzione: se memorizzi i ruoli nei JWT, devi avere un meccanismo per invalidare i token quando un ruolo cambia (ad esempio, scadenza breve del token o una blocklist).
Pensa anche all'ereditarietà dei ruoli: un Amministratore dell'organizzazione dovrebbe avere automaticamente il ruolo di Amministratore in tutti i workspace? La nostra regola pratica: i ruoli dell'organizzazione forniscono un tetto massimo, ma i ruoli del workspace possono essere più restrittivi. Ad esempio, un Amministratore dell'organizzazione può accedere a qualsiasi workspace, ma un Amministratore del workspace non può accedere alla fatturazione.
Modelli di fatturazione e pricing: meta-dati, non logica di business
La fatturazione è dove il multi-tenancy diventa concreto. Il tuo modello di pricing (per utente, per workspace, basato sull'utilizzo o a livelli) deve riflettersi nel tuo modello dati, ma il sistema di fatturazione dovrebbe essere disaccoppiato dall'applicazione principale. Utilizza un provider di fatturazione di terze parti (Stripe, Recurly, Chargebee) e conserva solo l'ID dell'abbonamento e l'ID del piano nel tuo database.
Raccomandiamo il seguente approccio per il database:
- Una tabella
plansche definisce lo slug del piano, il prezzo e i flag delle funzionalità (ad esempio,max_users,storage_gb,api_rate_limit). - Una tabella
organizationscon un campocurrent_plan_idebilling_provider_subscription_id. Collega le organizzazioni ai workspace tramite una tabella di join. - Una tabella
features(o una semplice colonna JSON) che memorizza le eccezioni. Ad esempio, se un cliente negozia una tariffa personalizzata, sovrascrivi il prezzo del piano a livello di organizzazione.
La parte più difficile è limitare l'accesso in base al piano. Hai due opzioni: applicare i limiti nell'applicazione (controllare max_users prima di invitare) o tramite conteggi di righe e trigger nel database. Preferiamo l'applicazione a livello applicativo perché produce messaggi di errore migliori per l'utente, ma aggiungiamo sempre un job di riconciliazione notturno che segnala le organizzazioni che superano i limiti.
Gli upgrade e downgrade dei piani richiedono una gestione attenta. Quando un cliente effettua un upgrade, concedi immediatamente l'accesso alle nuove funzionalità ma applica il pro-rating della fatturazione tramite il tuo provider. In caso di downgrade, devi decidere: bloccare l'accesso alle funzionalità che eccedono il nuovo piano o concedere un periodo di grazia? Raccomandiamo un periodo di grazia pari al ciclo di fatturazione corrente, dopo il quale applichi le restrizioni.
Una lezione dal campo: non lasciare mai che i fallimenti di fatturazione causino perdita di dati. Se un pagamento fallisce, degrada con garbo (ad esempio, limita le operazioni di scrittura) ma non eliminare i dati. Il tuo cliente pagherà—prima o poi.
Isolamento dei Tenant: Condiviso vs. Silo
L'isolamento è la decisione architetturale più importante. Il compromesso standard è tra un database condiviso (un database per tutti i tenant, con una colonna tenant_id su ogni tabella) e un database per tenant (ogni workspace ha il proprio database). Abbiamo sperimentato entrambi e, per la maggior parte dei progetti, abbiamo optato per un approccio ibrido.
- Condiviso con RLS rigoroso: Adatto per tenant piccoli e medi (sotto i 10.000 utenti ciascuno). La sicurezza a livello di riga è integrata in Postgres e utilizziamo una variabile di sessione (
app.tenant_id) per filtrare ogni query. È la soluzione più semplice da gestire e aggiornare. - Database per tenant: Necessario quando i tenant richiedono conformità rigorosa (HIPAA, SOC 2, GDPR per la residenza dei dati) o quando l'applicazione è I/O-intensive per tenant. L'overhead operativo è reale: le migrazioni dello schema devono essere applicate a centinaia di database, ma strumenti come Flyway e CI automatizzati lo rendono gestibile.
- Schema per tenant: Una via di mezzo che utilizza schemi separati all'interno di un unico database. Offre più isolamento di una tabella condivisa ma meno overhead operativo rispetto a database completi. Lo utilizziamo per i piani di fascia bassa e aggiorniamo i clienti a database per tenant se necessario.
Indipendentemente dalla strategia di isolamento, non consentire mai l'accesso diretto al database dal client. Instrada sempre attraverso un livello API che impone l'identità del tenant. E per il bene del tuo team di turno: non usare mai, mai tenant_id negli URL senza verificare che l'utente autenticato appartenga a quel tenant.
La migrazione dei dati tra livelli di isolamento è una realtà. Ad esempio, quando un tenant supera le capacità del database condiviso, potrebbe essere necessario migrarlo a un database dedicato. Pianifica per tempo: scrivi uno script di migrazione che esporti e importi i dati, e testalo con dati simili a quelli di produzione. Dovrebbe essere possibile eseguirlo senza tempi di inattività utilizzando un approccio blue-green.
Provisioning Automatico: Lascia Fare alla Macchina
Avviare manualmente nuovi tenant può funzionare per i primi dieci clienti, ma non scala. Come evidenziato dal recente brevetto di ContractorHUB, l'implementazione zero-touch è un fattore differenziante chiave per il SaaS multi-tenant [1]. Abbiamo costruito flussi di lavoro di provisioning che automatizzano tutto, dalla creazione del database (o clonazione dello schema) al seeding dei dati predefiniti e all'invio di email di benvenuto.
Una tipica pipeline di provisioning automatizzato:
- L'utente si registra, crea un'organizzazione e seleziona un piano.
- Un webhook dal tuo provider di fatturazione attiva un job di provisioning (ad esempio, una funzione serverless o un Job Kubernetes).
- Il job crea il livello di isolamento del tenant (schema o database), esegue le migrazioni iniziali e popola ruoli e impostazioni predefiniti.
- Un secondo job invia un'email con le istruzioni di accesso e i passaggi successivi.
- L'utente viene reindirizzato al nuovo spazio di lavoro, completamente funzionante, in pochi secondi.
L'idempotenza è fondamentale qui. Se il job di provisioning fallisce a metà, deve essere sicuro riprovare. Avvolgiamo l'intero processo in una macchina a stati con una colonna provisioning_status sulla riga dell'organizzazione: pending → creating → active → failed. Gli stati falliti vengono inviati a una coda di messaggi non elaborabili per l'intervento umano.
Non dimenticare di predisporre l'infrastruttura di supporto: record DNS per domini personalizzati, cache warmer CDN, limiti di rate API per tenant e alert di monitoraggio. Automatizza tutto ciò che può essere scriptato, perché i passaggi manuali verranno dimenticati sotto pressione.
Conclusione: La Mentalità Multi-Tenant
La multi-tenancy non è qualcosa che si aggiunge dopo il lancio. Deve guidare il tuo modello dati, il controllo degli accessi, l'integrazione della fatturazione e la strategia di deployment fin dal primo giorno. La buona notizia: se imposti correttamente questi quattro pilastri—workspace, ruoli, fatturazione, isolamento—il resto del tuo SaaS diventa notevolmente più facile da costruire e mantenere.
Ogni SaaS è diverso, ma i pattern sopra descritti ci hanno servito bene in vari settori. Che tu stia iniziando il tuo MVP o scalando a migliaia di tenant, ti incoraggiamo a riflettere attentamente su queste decisioni. E se desideri un secondo parere sulla tua architettura, siamo sempre felici di rivederla.


