Now-Next

SaaS-architectuur

Drie beslissingen in een SaaS-product die je later niet meer terugdraait

Klantscheiding, geld en rechten. Wat elk van de drie vooraf kost, wat het achteraf kost, en hoe je in tien minuten controleert hoe jouw product ervoor staat.

Chris van Eijk · · 6 min lezen

In een SaaS-product is bijna alles omkeerbaar. Een scherm bouw je opnieuw, een API-vorm versioneer je, een framework vervang je als het echt moet, en een prijsmodel verander je met een migratie en een mail. Dat is precies waarom software zo aantrekkelijk is om mee te beginnen: je hoeft het niet in één keer goed te hebben.

Drie dingen vallen daarbuiten. Ze kosten vooraf bij elkaar ongeveer een werkweek en ze zijn achteraf geen van drieën nog netjes recht te trekken. Dit is het overzicht: wat de beslissing is, wat hij vooraf kost, wat hij achteraf kost, en hoe je in tien minuten nagaat hoe jouw eigen product ervoor staat. Achter elk van de drie zit een artikel dat dieper gaat dan dit overzicht.

Welke beslissingen in een SaaS-product zijn later niet meer terug te draaien?

Drie: hoe je klanten uit elkaar houdt, hoe je bedragen opslaat en verdeelt, en hoe je rechten modelleert. Ze zijn onomkeerbaar omdat de reparatie niet alleen je code raakt maar je productiegeschiedenis — gegevens die bij de verkeerde klant zijn geweest, facturen die al de deur uit zijn, en gebruikers van wie niemand meer weet welke rol ze eigenlijk hadden. Vooraf kosten ze samen ongeveer vier tot vijf dagen werk; achteraf is elk van de drie een project waar geen enkele klant voor wil betalen.

De drie in één tabel

BeslissingDe klassieke foutVoorafAchterafWaaraan je merkt dat het mis is
Klanten scheideneen kolom tenant_id met alleen een filter in de applicatie± twee dagenweken, plus blijvende onzekerheid of je alles hebt gehadeen rapport, export of achtergrondtaak toont rijen van een andere klant
Geld rekenenbedragen in een float of double± een dagje migreert niet alleen je datamodel maar ook je geschiedenisde klant telt zelf op en komt een cent anders uit dan jij
Rechten modellereneen lijstje vinkjes per gebruikereen tot twee dagenvoor elke bestaande gebruiker raden welke rol hij eigenlijk had“welke vinkjes moet ik aanzetten om dit weer te laten werken?”

1. Klanten scheiden: twee sloten, niet één

De gewone aanpak is een kolom tenant_id op elke tabel en een filter in de applicatie. Dat werkt, tot het niet werkt — en de gaten zitten altijd op dezelfde vier plekken: een rauwe query voor een rapport dat te traag was, een achtergrondtaak zonder ingelogde gebruiker, een import of export die de gewone laag omzeilt, en een relatie die één stap te ver loopt.

Wat wél standhoudt is een tweede slot in de database zelf: row-level security in PostgreSQL, waarbij de sessie één variabele zet en het beleid op de tabel de rest weigert. Een rauwe query krijgt dan nul rijen, een achtergrondtaak zonder context krijgt niets, en een import die de ORM omzeilt ook niet. Dat is het hele punt: de tweede laag beschermt je tegen de fouten die je in de eerste gaat maken.

Uitgebreid: multi-tenant vanaf dag één.

2. Geld rekenen: centen, geen floats

Een verkeerd getaltype geeft geen foutmelding. Het geeft een uitkomst die er goed uitziet en die er af en toe een cent naast zit, en die afwijking reist via factuurregels, btw en totalen omhoog tot de balans niet meer sluit. De schade is niet de cent maar het vertrouwen.

Bewaar bedragen daarom als hele centen in een integer, met de munt ernaast. En weet dat integers het optellen oplossen maar niet het delen: zodra je een bedrag verdeelt, blijft er een rest over die iemand moet krijgen, en dat is een productbeslissing die ergens opgeschreven hoort te staan.

Uitgebreid: bedragen in centen, geen floats.

3. Rechten modelleren: rollen, geen vinkjes

Vinkjes per gebruiker beginnen als een redelijk antwoord op een redelijk verzoek en lopen bij de twintigste klant vast in drie richtingen tegelijk: het is niet meer te testen, niet meer uit te leggen en niet meer te migreren. Rechten horen bij een rol, uit een vaste en kleine verzameling die benoemd is naar wat iemand kan doen en niet naar het scherm waar het op staat.

Daar hoort één onderscheid bij dat ook ervaren teams verkeerd leggen: een rol bepaalt wát iemand mag, niet waaróver. Dat tweede is de klantgrens, en die hoort in de database te staan — anders hangt de scheiding tussen twee bedrijven alsnog aan een if in de applicatie.

Uitgebreid: rechten: rollen, geen vinkjes.

Controleer je eigen product in tien minuten

Vier controles, en je hebt ze alle vier zelf in handen. Je hebt er geen audit voor nodig en geen toegang tot iemands broncode behalve die van jezelf.

1. Zet de klantcontext uit en kijk wat er terugkomt. Draai een willekeurige query zonder ingelogde gebruiker — vanuit een console, een rapport of een achtergrondtaak. Het goede antwoord is nul rijen. Krijg je gegevens te zien, dan hangt je klantscheiding aan één slot, en dat slot zit in code die iemand een keer omzeilt.

2. Zoek het woord float in de kolommen waar bedragen staan. Eén hit is genoeg om het te weten. Staat er een decimaal type, kijk dan of er één functie is die verdeelt — en of er een test is die controleert dat de som van de regels exact het totaal is.

3. Bereken dezelfde factuur twee keer, met de regels in een andere volgorde. Komt er een ander bedrag uit, dan hangt je verdeling aan de volgorde van je gegevens en geeft hij na de eerstvolgende migratie een ander antwoord dan ervoor. Dit is de test die bijna niemand schrijft en die het vaakst iets vindt.

4. Tel de eindpunten in je applicatie en tel de regels in je rechtenmatrix. Zijn dat verschillende getallen, dan is er een handeling die niemand aan een rol heeft gekoppeld. Laat die test de lijst met eindpunten uit de applicatie zelf halen in plaats van hem over te typen: een matrix die je met de hand bijhoudt, dekt precies de code van vorig jaar.

Waarom juist deze drie

De grens is scherper dan hij lijkt. Een beslissing is omkeerbaar zolang de reparatie alleen je code raakt. Deze drie raken je geschiedenis, en dan is de vraag niet meer hoe zetten we het om maar welk van de twee antwoorden was waar — het opgeslagen totaal of de som van de regels, de rol die iemand had of de vinkjes die er nu staan. Dat is geen technische vraag meer, en er is niemand die hem voor je kan beantwoorden.

Daar komt bij dat geen van de drie iets oplevert wat je aan een klant kunt laten zien. Ze zijn alle drie volledig onzichtbaar zolang ze goed zijn, en dat is precies waarom ze de aandacht zelden krijgen die ze verdienen. Wij hebben ze bij booxx en Pilot-Next alle drie vooraf moeten beslissen, inclusief de keren dat we het bijna verkeerd hadden.

Begin je iets nieuws, dan is dit het eerste waar wij naar kijken als we een SaaS-product bouwen. Staat er al iets en blijft een van de vier controles hierboven aan je knagen, dan gaat het gesprek meestal over een bestaand platform doorontwikkelen. In beide gevallen: stuur een mail — een half uur is meestal genoeg om te weten of het klopt.

Laten we praten

Wat gaan we bouwen?

Eén gesprek is genoeg om te weten of we bij elkaar passen. Vertel wat je voor je ziet — wij zeggen hoe snel dat kan, en of wij daar de juiste partij voor zijn.

Start het gesprek