iKonekt

Separation

Gränsen som databasen håller, inte koden

Varje CRM påstår sig vara multi-tenant. Påståendet är billigt; det som spelar roll är vilket lager som håller linjen. Om svaret är "vår applikation lägger alltid till rätt filter", då är garantin bara så bra som den mest utvilade utvecklaren som någonsin skrivit en fråga.

iKonekt var multi-tenant från sin första migration i stället för att byggas om i efterhand, vilket låter som en skrytfras men egentligen är en erkändhet: att bygga om det i efterhand är nästan omöjligt att göra övertygande, och alla som försökt har en historia att berätta.

Separationen bor i databasen. Vart och ett av de tjugosex tabellerna bär på den tenant det tillhör, och policyn som kontrollerar det körs vid varje läsning och varje skrivning, helt under applikationen. En fråga som glömmer gränsen returnerar inte någon annans kunder. Den returnerar ingenting.

Radnivåsäkerhet, påtvingad

Inte en konvention, inte en kodgranskningsregel. Databasen vägrar. Sjuttiotvå policys, skrivna ut en och en i stället för genererade — för en genererad policy är en policy som ingen har läst.

Sammansatta nycklar

En barnpost refererar till sin tenant och sin förälder tillsammans, som ett par. En felaktig identifierare från fel företag löser sig inte — den är helt enkelt inte en giltig referens.

Ingen standardtenant, någonsin

En begäran utan scope blir inte tyst en begäran för tenant noll. Den kastar ett fel innan den når databasen. Det finns inget "unscoped"-läge att glömma stänga av.

Buggen som inte kunde göra sig hörd

Medan tenancy-arbetet pågick var de flesta misstagen högljudda. Ge två företag samma kunddomän och databasen protesterar omedelbart, med felkod och stack trace; du fixar det före lunch.

En protesterade inte. En tabell med redigerbara prompt-överskridanden nycklades enbart på promptens typ — inte på typ och tenant. Ett andra företag som redigerade sin egen kopia skulle ha tyst skrivit över det första företagets, genom helt giltig SQL, utan fel, utan varning och utan fallande test. Den hittades genom att läsa vart och ett av de återstående unika indexen efter en nyckeländring, ett i taget, på misstanken att de högljudda hade sällskap.

Vi nämner det för att det är den ärliga formen av det här arbetet. Separation är inte en funktion du slår på; det är en vana att läsa de tråkiga delarna av schemat i förväntan på att något där inne inte håller med dig.

Testerna, för protokollets skull: 942 stycken, körda mot en databas byggd från noll vid varje ändring. De finns inte där för att bevisa att designen är smart. De finns där för att felmoden hos just den här designen är tyst, och tysta fel behöver någon som ropar åt dem.

Vad separation ger en vanlig människa

  • En grupp kan driva flera företag från en installation, och en säljare i det ena kommer aldrig att se en kund i det andra — inte genom policy, utan genom konstruktion.
  • Ett partnerprogram, en uppsättning prompts, ett anspråk på en kund: allt är scopat per företag, så att en tenants konfiguration inte kan bli allas.
  • En begäran om radering hedras inom en gräns i stället för över en gemensam hög, och det är det som gör det möjligt att svara ärligt.
  • Och ingen behöver komma ihåg något av det. Det är poängen — en garanti som bygger på att bli ihåkommen är ingen garanti.

En rad till som inte handlar om databaser

Varje syskontjänst i familjen håller sitt eget namngivna credential. Inget talar med ett delat, så ingen tjänst kan av misstag agera som en annan — en liten disciplin som kom direkt av att en gång ha haft en delad token och inte tyckt om det.

Det är samma instinkt som databasregeln. Gör det felaktiga omöjligt i stället för avrått, och du lägger din uppmärksamhet på kunder i stället för på vaksamhet.

GränsenUnder applikationen
  • 126 tabellerVart och ett bär sin tenant, med kontrollen påtvingad.
  • 272 policysSkrivna ut individuellt, så att var och en har lästs av en människa.
  • 3942 testerMot en databas byggd från noll, vid varje ändring.
  • 40 standardtenanterEn begäran utan scope når aldrig datat.

Mätt på det livebyggda

"Vår applikation filtrerar alltid på företag."

"Alltid" gör ett stort arbete i den meningen.

Flytta gränsen ner i databasen och en glömd WHERE-sats returnerar ingenting i stället för någon annans kunder. En tom skärm är ett bättre misslyckande än en pinsam presentation.

För grupper som driver flera varumärken →