Adskillelse
Grænsen, som databasen holder, ikke koden
Hvert CRM hævder at være multi-tenant. Påstanden er billig; det, der tæller, er, hvilket lag der holder linjen. Hvis svaret er "vores applikation tilføjer altid det rigtige filter", så er garantien kun så god som den mest udhvilede udvikler, der nogensinde har skrevet en forespørgsel.
iKonekt var multi-tenant fra sin første migration i stedet for at blive eftermonteret bagefter, hvilket lyder som en pralende udtalelse og i virkeligheden er en indrømmelse: at eftermontere det er tæt på umuligt at gøre overbevisende, og alle, der har prøvet, har en historie.
Adskillelsen bor i databasen. Hver af de seksogtyve tabeller bærer den tenant, den tilhører, og den politik, der tjekker det, kører ved hver læsning og hver skrivning, helt under applikationen. En forespørgsel, der glemmer grænsen, returnerer ikke en andens kunder. Den returnerer ingenting.
Sikkerhed på rækkeniveau, gennemtvunget
Ikke en konvention, ikke en kodegennemgangsregel. Databasen nægter. Tooghalvfjerds politikker, skrevet ud én ad gangen frem for genereret — for en genereret politik er en politik, ingen har læst.
Sammensatte nøgler
En underpost refererer til sin tenant og sin forælder sammen, som et par. En løs identifikator fra det forkerte firma kan ikke opløses — den er simpelthen ikke en gyldig reference.
Ingen standard-tenant, nogensinde
En forespørgsel uden et scope bliver ikke stille til en forespørgsel på tenant nul. Den kaster en fejl, før den når databasen. Der er ingen "unscoped"-tilstand at glemme at slå fra.
Fejlen, der ikke kunne melde sig selv
Mens tenancy-arbejdet blev udført, var de fleste fejl højlydte. Giv to firmaer det samme kundedomæne, og databasen gør indvending med det samme, med en fejlkode og et stack trace; du fikser det inden frokost.
Én gjorde ikke indvending. En tabel med redigerbare prompt-overskrivelser var nøglet på promptens slone alene — ikke på slone og tenant. Et andet firma, der redigerede deres egen kopi, ville have overskrevet det første firmas i stilhed, gennem helt gyldig SQL, uden fejl, uden advarsel og uden en fejlende test. Den blev fundet ved at læse alle resterende unikke indekser efter en nøgleændring, én ad gangen, på mistanke om, at de højlydte havde selskab.
Vi nævner det, fordi det er den ærlige form for dette arbejde. Adskillelse er ikke en funktion, du slår til; det er en vane med at læse de kedelige dele af skemaet i den antagelse, at noget derinde er uenig med dig.
Testene, for god ordens skyld: 942 af dem, kørt mod en database, der bygges fra nul ved hver ændring. De er der ikke for at bevise, at designet er smart. De er der, fordi fejlmåden ved netop dette design er lydløs, og lydløse fejl har brug for nogen, der råber på deres vegne.
Hvad adskillelse giver et normalt menneske
- En gruppe kan drive flere firmaer fra én installation, og en sælger i det ene vil aldrig se en kunde fra det andet — ikke som politik, men ved konstruktion.
- En partnerprogram, et sæt prompts, et krav på en kunde: alt er scoperet pr. firma, så én tenants konfiguration ikke kan blive alles.
- En anmodning om sletning imødekommes inden for en grænse i stedet for på tværs af en delt bunke, og det er netop dét, der gør det muligt at svare ærligt.
- Og ingen behøver at huske noget af det. Det er pointen — en garanti, der afhænger af at blive husket, er ikke en garanti.
Endnu en linje, der ikke handler om databaser
Hver søstertjeneste i familien holder sit eget navngivne credential. Intet taler med et delt, så ingen tjeneste kan ved et uheld agere som en anden — en lille disciplin, der kom direkte fra engang at have haft et delt token og ikke have nydt det.
Det er den samme instinkt som databasereglen. Gør det forkerte umuligt frem for frarådet, og du bruger din opmærksomhed på kunder i stedet for på årvågenhed.
- 126 tabellerHver enkelt bærer sin tenant, med kontrollen gennemtvunget.
- 272 politikkerSkrevet ud individuelt, så hver enkelt er blevet læst af et menneske.
- 3942 testsMod en database, der bygges op fra nul ved hver ændring.
- 40 standard-lejereEn forespørgsel uden et scope når aldrig frem til dataene.
Målt på den live-byggede version

„Vores applikation filtrerer altid efter virksomhed.“
Ordet altid gør et stort arbejde i den sætning.
Flyt grænsen ned i databasen, og en glemt WHERE-klausul returnerer ingenting i stedet for en andens kunder. En tom skærm er en bedre fejl end en akavet introduktion.
Til grupper med flere brands →