Het begint bijna altijd hetzelfde. Je laat een maatwerkapplicatie bouwen omdat de standaardpakketten niet aansluiten op jouw manier van werken. Het draait, het bevalt, en dan komt de vraag van een collega-ondernemer: "Kan ik dat ook gebruiken?"
Op dat moment verandert er iets fundamenteels. Je applicatie was gebouwd voor één organisatie — die van jou. Vanaf nu moet hij gegevens van meerdere organisaties bedienen zonder dat die elkaar ooit te zien krijgen. Dat is geen kwestie van een extra tabelletje. Het raakt je datamodel, je beveiliging, je hosting en je onderhoud.
Wat multi-tenancy eigenlijk betekent
Een tenant is simpelweg één klant of organisatie binnen jouw applicatie. Multi-tenancy betekent dat één stuk software meerdere tenants bedient, waarbij elke tenant alleen zijn eigen gegevens ziet.
De aantrekkingskracht is duidelijk: je onderhoudt één codebase, je rolt één update uit en iedereen profiteert. De keerzijde is even duidelijk: één fout in de scheiding tussen tenants en klant A kijkt in de gegevens van klant B. Dat is niet alleen een technisch probleem, maar direct een datalek onder de AVG.
In Laravel zijn er grofweg drie manieren om dit aan te pakken.
Optie 1: één database, gedeelde tabellen
De meest gebruikte aanpak. Alle tenants delen dezelfde database en dezelfde tabellen, en elke rij krijgt een kolom die aangeeft bij welke tenant hij hoort — meestal een tenant_id.
Bij elke query moet die kolom worden meegefilterd. Doe je dat handmatig, dan is het een kwestie van tijd voordat iemand het ergens vergeet. Laravel biedt hiervoor global scopes: een filter dat automatisch aan elke Eloquent-query wordt toegevoegd, zodat vergeten simpelweg geen optie meer is. Pakketten zoals stancl/tenancy en spatie/laravel-multitenancy bouwen hier gereedschap omheen.
Sterk punt: eenvoudig te beheren. Eén database, één set migraties, makkelijk schaalbaar naar veel kleine klanten. Zwak punt: de scheiding leunt volledig op je applicatiecode. Een fout in een query, een rapportage of een export kan gegevens laten weglekken.
Optie 2: een aparte database per klant
Elke tenant krijgt zijn eigen database, met identieke tabellen. Bij binnenkomst bepaalt de applicatie — meestal op basis van het subdomein of de ingelogde gebruiker — met welke database de verbinding wordt gemaakt.
Sterk punt: de scheiding zit op infrastructuurniveau. Een fout in een query kan geen gegevens van een andere klant raken, omdat die simpelweg niet in beeld zijn. Ook prettig als een klant vraagt om een eigen back-up, een eigen export, of verwijdering van al zijn gegevens: dat is dan één afgebakende handeling. Zwak punt: meer beheer. Migraties moeten over alle databases lopen, en als er één faalt zit je met een omgeving die deels bijgewerkt is. Rapportages over alle klanten heen worden lastiger.
Optie 3: volledig gescheiden installaties
De radicale variant: elke klant krijgt zijn eigen installatie, eigen database en eigen omgeving. Technisch is dat nauwelijks nog multi-tenancy te noemen.
Dit is verdedigbaar bij een klein aantal grote klanten met zware eisen aan isolatie of met veel klantspecifiek maatwerk. Maar het schaalt slecht: elke update moet je overal uitrollen, en het verschil tussen omgevingen groeit vanzelf.
Waar het in de praktijk misgaat
De databasekeuze is meestal het makkelijkste deel. De problemen zitten in de hoeken waar je niet aan denkt:
- Achtergrondtaken. Een job die in de wachtrij belandt, weet niet vanzelf voor welke tenant hij draait. Wordt die context niet expliciet meegegeven, dan draait je nachtelijke verwerking zomaar op de verkeerde gegevens.
- Cache. Een cachesleutel als
dashboard_totalenis niet tenant-specifiek. De eerste klant die de pagina laadt, vult de cache voor iedereen. - Bestandsopslag. Uploads, PDF's en exports moeten per tenant gescheiden worden opgeslagen — en de download-URL moet controleren of de gebruiker er recht op heeft.
- E-mail en instellingen. Elke klant wil zijn eigen logo, afzender en huisstijl. Dat betekent configuratie per tenant, niet één centrale
.env. - Zoeken en rapportages. Juist de queries die je later toevoegt, buiten het gebaande pad om, zijn de plek waar de tenantfilter wordt vergeten.
Hoe kies je?
Vier vragen brengen je meestal snel bij een antwoord:
- Hoeveel klanten verwacht je? Veel kleine klanten pleiten voor een gedeelde database; een handvol grote klanten maakt een database per tenant goed haalbaar.
- Hoe zwaar zijn de eisen aan isolatie? Werk je met gevoelige gegevens, of hebben je klanten zelf certificeringseisen, dan is scheiding op infrastructuurniveau een stuk beter uit te leggen dan "wij filteren netjes in de code".
- Hoeveel verschilt het per klant? Kleine verschillen los je op met instellingen. Wijken processen structureel af, dan loop je met één gedeelde codebase vast.
- Wie beheert het straks? Een database per tenant vraagt om geautomatiseerde uitrol en monitoring. Zonder dat wordt elke update een handmatige klus.
Begin klein, maar leg de basis goed
Je hoeft niet meteen alles te bouwen. Wel is dit de fase waarin je keuzes lastig terug te draaien zijn: achteraf tenant-isolatie inbouwen in een applicatie die er nooit rekening mee hield, is aanzienlijk meer werk dan het vanaf het begin goed inrichten.
Onze aanpak is daarom pragmatisch. We beginnen met het datamodel en de isolatie — dat fundament moet kloppen. Daarna komen de praktische zaken: uitrol, monitoring, back-ups per klant en het aanmaken van een nieuwe tenant zonder handwerk. Zo groeit je applicatie mee met het aantal klanten, in plaats van dat elke nieuwe klant een project op zich wordt.
Denk je erover om je maatwerkapplicatie beschikbaar te maken voor meerdere klanten? Wij helpen je de architectuurkeuze te maken die past bij je ambitie én je budget. Neem gerust contact met ons op voor een vrijblijvend gesprek.
