Il problema: un deployment per cliente non scala
Hai un SaaS gestionale che usi con 5 clienti. Ogni cliente ha la propria istanza: 5 server, 5 database, 5 deployment. Quando rilasci un aggiornamento, lo deployi 5 volte. Quando correggi un bug, lo patchi 5 volte. Quando il sesto cliente firma il contratto, crei la sesta istanza da zero. Con 50 clienti, gestire l'infrastruttura diventa il lavoro principale — non lo sviluppo.
La Multi-Tenancy risolve questo: una singola istanza dell'applicazione serve più clienti (tenant), ognuno con i propri dati isolati. Un deployment, un aggiornamento, un'infrastruttura — molti clienti.
Le tre strategie di isolamento
1. Database separati
Ogni tenant ha il proprio database. L'applicazione e condivisa, ma alla connessione seleziona il database del tenant. Massimo isolamento dei dati: un tenant non può mai vedere i dati di un altro, nemmeno per bug. Facilità backup e restore per singolo tenant. Svantaggio: tanti database da gestire e migrare.
2. Schema separati (stesso database)
Un database, ma ogni tenant ha il proprio schema (PostgreSQL) o prefisso tabelle (MySQL). Buon isolamento con meno overhead di gestione. Le migrazioni vanno eseguite per ogni schema. Funziona bene fino a centinaia di tenant.
3. Tabelle condivise con tenant_id
Un database, uno schema, e ogni tabella ha una colonna tenant_id. Ogni query filtra per tenant: WHERE tenant_id = :current_tenant. Minimo overhead, massima semplicità, ma il rischio di data leak e reale: dimenticare il filtro in una query espone i dati di tutti i tenant. Servono guardie a livello di framework.
Esempio pratico: tenant_id con middleware
La strategia più comune in PHP e il tenant_id con middleware:
- Un middleware identifica il tenant dalla request (subdomain, header, token JWT) e lo salva nel contesto
- Un global scope sul Model aggiunge automaticamente
WHERE tenant_id = :ida ogni query - Un observer sul Model imposta automaticamente il
tenant_idsu ogni INSERT - Un policy verifica che l'utente possa accedere solo ai dati del proprio tenant
Il vantaggio: il codice dei controller e dei service non sa di essere multi-tenant. Il filtro e trasparente a livello di infrastruttura.
Identificazione del tenant
-
Subdomain:
acme.app.com,globex.app.com. Intuitivo per gli utenti. Richiede DNS wildcard. -
Path:
app.com/acme/,app.com/globex/. Più semplice da configurare. Meno elegante. - Header/Token: il tenant ID nel JWT o in un header custom. Ideale per API. Invisibile all'utente.
- Domain custom: ogni tenant ha il proprio dominio. Massima personalizzazione. Più complesso da gestire.
Aspetti critici
- Sicurezza: il data leak tra tenant e il rischio numero uno. Ogni query, ogni endpoint, ogni export deve filtrare per tenant. Servono test dedicati.
-
Performance: un tenant con molti dati non deve rallentare gli altri. Indici su
tenant_id, connection pooling, e monitoraggio per tenant. - Personalizzazione: i tenant vogliono loghi, colori, campi custom. Fino a che punto la personalizzazione e supportata senza fork del codice?
- Billing: ogni tenant ha un piano diverso con limiti diversi. Il sistema deve tracciare l'uso per tenant.
- Migrazioni: con database/schema separati, una migrazione va eseguita N volte. Con tenant_id condiviso, una volta sola ma con rischi maggiori.
Quando usare Multi-Tenancy
- Usa Multi-Tenancy quando costruisci un SaaS che servira più clienti con la stessa applicazione
- Usa database separati quando l'isolamento dei dati e un requisito legale (sanita, finanza)
- Usa tenant_id condiviso quando la semplicità e la priorità e i tenant sono tanti con dati piccoli
- Non usare Multi-Tenancy se hai meno di 5 clienti: il costo di implementazione non si giustifica
- Non usare Multi-Tenancy se ogni cliente ha requisiti radicalmente diversi: a quel punto servono istanze separate
La Multi-Tenancy non e solo una tecnica di database: e un'architettura che pervade ogni aspetto dell'applicazione — dal routing alla sicurezza, dal billing al deploy. Quando funziona, scala elegantemente da 5 a 5.000 clienti con la stessa infrastruttura. Quando e implementata male, espone i dati di un cliente a un altro — e quello e il tipo di bug che fa perdere contratti.
Top comments (0)