Separation
Di boundary wey di database dey keep, no be di code
Every CRM dey claim say dem multi-tenant. Di claim cheap; wetin matter na which layer dey hold di line. If di answer na "our application always add di correct filter", den di guarantee only good as di developer wey rest least wey ever write a query.
iKonekt bin multi-tenant from im first migration instead of to add am later, wey sound like boast but really na admission: to add am later near impossible to do well, and everybody wey don try get story.
Separation dey live inside di database. Every one of di twenty-six tables carry di tenant wey e belong to, and di policy wey dey check am dey run on every read and every write, completely below di application. A query wey forget di boundary no go return another person customers. E go return nothing.
Row-level security, forced
No be convention, no be code review rule. Di database dey refuse. Seventy-two policies, written one by one instead of generated — because generated policy na policy wey nobody don read.
Composite keys
A child record reference im tenant and im parent together, as pair. A stray identifier from di wrong company no go resolve — e simply no be valid reference.
No difolt tenant, eva
A request wey no get scope no go quietly become request for tenant zero. E go throw before e reach di database. No "unscoped" mode dey to forget to turn off.
Di bug wey no fit announce itself
While dem dey do di tenancy work, most of di mistakes loud. Give two companies di same customer domain and di database object am immediately, with error code and stack trace; you go fix am before lunch.
One no object. A table of editable prompt overrides bin key on di prompt kind alone — no be on kind and tenant. A second company wey edit dem own copy for don quietly overwrite di first company own, through completely valid SQL, with no error, no warning, and no failing test. Dem find am by reading every remaining unique index after dem change a key, one by one, on di suspicion say di loud ones get company.
We mention am because na di honest shape of dis work. Separation no be feature wey you switch on; na habit of reading di boring parts of di schema on di assumption say something inside dey disagree with you.
Di tests, for di record: 942 of dem, run against database wey dem rebuild from zero on every change. Dem no dey there to prove say di design clever. Dem dey there because di failure mode of dis particular design dey silent, and silent failures need person wey go shout for dem behalf.
Wetin separation buy a normal person
- A group fit run several companies from one install, and a seller inside one no go ever see customer of another — no be by policy, by construction.
- A partner programme, a set of prompts, a claim on a customer: all scoped per company, so one tenant configuration no fit become everybody own.
- An erasure request dem honour am inside a boundary instead of across a shared pile, and na wetin make am possible to answer honestly.
- And nobody need remember any of am. Na di point be dat — a guarantee wey depend on to remember am no be guarantee.
One more line wey no be about databases
Every sibling service inside di family hold im own named credential. Nothing dey speak with shared one, so no service fit accidentally act as another — a small discipline wey come directly from once having a shared token and no enjoying am.
Na the same instinct like the database rule. Make the wrong thing impossible instead of just discouraging am, and you go use your attention on customers instead of on watching out.
- 126 tablesEvery one carry im tenant, with the check forced on.
- 272 policiesDem write am out one by one, so person don read each one.
- 3942 testsAgainst a database wey dem rebuild from zero, every time change happen.
- 40 default tenantsRequest wey no get scope no go ever reach the data.
Dem measure am on the live build

“Our application dey always filter by company.”
That 'always' dey carry plenty weight for that sentence.
Move the boundary down enter the database, and forgotten WHERE clause go return nothing instead of another person customers. Empty screen na better failure pass awkward introduction.
For groups wey dey run plenty brands →