Separazione
Il confine lo tiene il database, non il codice
Ogni CRM dichiara di essere multi-tenant. La dichiarazione costa poco; ciò che conta è quale livello tiene la linea. Se la risposta è "la nostra applicazione aggiunge sempre il filtro giusto", allora la garanzia vale solo quanto lo sviluppatore meno riposato che abbia mai scritto una query.
iKonekt era multi-tenant dalla sua prima migrazione, non adattato in seguito, il che suona come un vanto ed è in realtà un'ammissione: adattarlo dopo è quasi impossibile da fare in modo credibile, e chiunque ci abbia provato ha una storia da raccontare.
La separazione vive nel database. Ognuna delle ventisei tabelle porta con sé il tenant a cui appartiene, e la policy che lo verifica gira a ogni lettura e a ogni scrittura, interamente al di sotto dell'applicazione. Una query che dimentica il confine non restituisce i clienti di qualcun altro. Non restituisce nulla.
Sicurezza a livello di riga, imposta
Non una convenzione, non una regola di code review. Il database si rifiuta. Settantadue policy, scritte una a una invece che generate — perché una policy generata è una policy che nessuno ha letto.
Chiavi composite
Un record figlio riferisce al suo tenant e al suo genitore insieme, come coppia. Un identificatore estraneo dell'azienda sbagliata non si risolve — semplicemente non è un riferimento valido.
Nessun tenant predefinito, mai
Una richiesta senza uno scope non diventa silenziosamente una richiesta per il tenant zero. Fallisce prima di arrivare al database. Non esiste una modalità "unscoped" da dimenticare di spegnere.
Il bug che non poteva farsi annunciare
Mentre si lavorava alla multi-tenancy, la maggior parte degli errori era rumorosa. Dai a due aziende lo stesso dominio cliente e il database si oppone immediatamente, con un codice di errore e uno stack trace; la correggi prima di pranzo.
Uno non ha obiettato. Una tabella di override modificabili dei prompt era indicizzata solo sul tipo del prompt — non su tipo e tenant. Una seconda azienda che modificava la propria copia avrebbe sovrascritto silenziosamente quella della prima, tramite SQL del tutto valido, senza errori, senza avvisi e senza test falliti. È stato trovato leggendo ogni indice univoco rimasto dopo aver modificato una chiave, uno alla volta, col sospetto che anche quelli rumorosi avessero un compagno.
Lo menzioniamo perché è la forma onesta di questo lavoro. La separazione non è una funzionalità che si attiva; è l'abitudine di leggere le parti noiosi dello schema partendo dal presupposto che qualcosa lì dentro sia in disaccordo con te.
I test, per la cronaca: 942, eseguiti su un database ricostruito da zero a ogni modifica. Non ci sono per dimostrare che il design è ingegnoso. Ci sono perché la modalità di guasto di questo particolare design è silenziosa, e i guasti silenziosi hanno bisogno di qualcuno che gridi per conto loro.
Cosa la separazione compra a una persona normale
- Un gruppo può gestire più aziende da una sola installazione, e un venditore di una non vedrà mai un cliente di un'altra — non per policy, ma per costruzione.
- Un programma per partner, un insieme di prompt, una rivendicazione su un cliente: tutto con scope per azienda, così la configurazione di un tenant non può diventare quella di tutti.
- Una richiesta di cancellazione viene onorata entro un confine anziché attraverso un mucchio condiviso, ed è questo che rende possibile rispondere onestamente.
- E nessuno deve ricordarsene nulla. È questo il punto — una garanzia che dipende dal farsi ricordare non è una garanzia.
Un'altra riga che non riguarda i database
Ogni servizio della famiglia possiede la propria credenziale con nome. Nulla comunica con una credenziale condivisa, quindi nessun servizio può agire per sbaglio come un altro — una piccola disciplina nata direttamente dall'aver avuto un token condiviso e dall'essersene pentiti.
È lo stesso istinto della regola sui database. Rendi impossibile la cosa sbagliata invece di scoraggiarla, e dedicherai la tua attenzione ai clienti invece che alla vigilanza.
- 126 tabelleOgnuna porta il proprio tenant, con il vincolo forzato.
- 272 policyScritte una per una, così ognuna è stata letta da una persona.
- 3942 testContro un database ricostruito da zero, a ogni modifica.
- 40 tenant predefinitiUna richiesta senza ambito non arriva mai ai dati.
Misurato sulla build live

«La nostra applicazione filtra sempre per azienda.»
In quella frase, «sempre» fa un lavoro enorme.
Sposta il confine giù nel database e una clausola WHERE dimenticata non restituisce nulla invece dei clienti di un altro. Una schermata vuota è un fallimento migliore di una presentazione imbarazzante.
Per le realtà che gestiscono più marchi →