Séparation
La frontière que la base de données maintient, pas le code
Chaque CRM prétend être multi-tenant. La prétention ne coûte rien ; ce qui compte, c'est la couche qui tient la ligne. Si la réponse est « notre application ajoute toujours le bon filtre », alors la garantie ne vaut que par le développeur le moins reposé ayant jamais écrit une requête.
iKonekt était multi-tenant dès sa première migration plutôt que réaménagé après coup, ce qui ressemble à une vantardise et constitue en réalité un aveu : le réaménager de manière convaincante est presque impossible, et tous ceux qui ont essayé ont une histoire à raconter.
La séparation vit dans la base de données. Chacune des vingt-six tables porte le tenant auquel elle appartient, et la politique qui le vérifie s'exécute à chaque lecture et à chaque écriture, entièrement en dessous de l'application. Une requête qui oublie la frontière ne renvoie pas les clients d'un autre. Elle ne renvoie rien.
Sécurité au niveau des lignes, imposée
Pas une convention, pas une règle de revue de code. La base de données refuse. Soixante-douze politiques, rédigées une par une plutôt que générées — car une politique générée est une politique que personne n'a lue.
Clés composites
Une fiche enfant référence son tenant et son parent ensemble, en paire. Un identifiant égaré de la mauvaise entreprise ne se résout pas — il n'est tout simplement pas une référence valide.
Aucun tenant par défaut, jamais
Une requête sans périmètre ne devient pas discrètement une requête pour le tenant zéro. Elle échoue avant d'atteindre la base de données. Il n'existe aucun mode « sans périmètre » qu'on pourrait oublier de désactiver.
Le bug qui ne pouvait pas se signaler
Pendant les travaux sur la location des données, la plupart des erreurs étaient bruyantes. Donnez à deux entreprises le même domaine client et les objets de base de données immédiatement, avec un code d'erreur et une trace de pile ; vous corrigez avant le déjeuner.
L'une n'a pas protesté. Une table de remplacements de prompts modifiables était indexée sur le seul type du prompt — et non sur le type et le locataire. Une seconde entreprise modifiant sa propre copie aurait écrasé silencieusement celle de la première, par du SQL parfaitement valide, sans erreur, sans avertissement et sans test en échec. Cela a été découvert en relisant chaque index unique restant après modification d'une clé, un par un, sur le soupçon que les erreurs bruyantes avaient de la compagnie.
Nous le mentionnons parce que c'est la forme honnête de ce travail. La séparation n'est pas une fonctionnalité que l'on active ; c'est une habitude de lire les parties ennuyeuses du schéma en supposant que quelque chose là-dedans vous contredit.
Les tests, pour mémoire : 942 d'entre eux, exécutés sur une base de données reconstruite de zéro à chaque modification. Ils ne sont pas là pour prouver que la conception est ingénieuse. Ils sont là parce que le mode de défaillance de cette conception particulière est silencieux, et les défaillances silencieuses ont besoin de quelqu'un qui crie en leur nom.
Ce que la séparation apporte à une personne ordinaire
- Un groupe peut gérer plusieurs entreprises depuis une seule installation, et un vendeur de l'une ne verra jamais un client d'une autre — non par politique, mais par construction.
- Un programme de partenaires, un ensemble de prompts, une revendication sur un client : tout est délimité par entreprise, de sorte que la configuration d'un locataire ne puisse devenir celle de tous.
- Une demande d'effacement est honorée dans une frontière plutôt qu'à travers un tas partagé, ce qui rend possible une réponse honnête.
- Et personne n'a besoin de s'en souvenir. C'est là tout l'intérêt — une garantie qui dépend d'être retenue n'est pas une garantie.
Une ligne de plus qui ne concerne pas les bases de données
Chaque service frère de la famille détient son propre identifiant nommé. Rien ne parle avec un identifiant partagé, donc aucun service ne peut agir accidentellement comme un autre — une petite discipline née directement d'avoir eu un jour un jeton partagé et de ne pas l'avoir apprécié.
C'est le même instinct que la règle de la base de données. Rendre l'erreur impossible plutôt que déconseillée, et vous consacrez votre attention aux clients au lieu de la vigilance.
- 126 tablesChacune porte son locataire, avec la contrainte forcée.
- 272 politiquesRédigées individuellement, de sorte que chacune a été lue par une personne.
- 3942 testsSur une base de données reconstruite de zéro, à chaque modification.
- 40 locataire par défautUne requête sans périmètre n'atteint jamais les données.
Mesuré sur la version en production

« Notre application filtre toujours par entreprise. »
Le mot « toujours » fait beaucoup de travail dans cette phrase.
Déplacez la frontière vers le bas, dans la base de données, et une clause WHERE oubliée ne renvoie rien au lieu des clients de quelqu'un d'autre. Un écran vide est une meilleure défaillance qu'une présentation embarrassante.
Pour les groupes gérant plusieurs marques →