DEV Community

Cover image for Multi-Tenancy: un'applicazione, molti clienti
Dev-Iadicola
Dev-Iadicola

Posted on • Originally published at iadicola.it

Multi-Tenancy: un'applicazione, molti clienti

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 = :id a ogni query
  • Un observer sul Model imposta automaticamente il tenant_id su 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.


👉 Leggi l'articolo completo su iadicola.it

Top comments (0)