Architectuurkeuze 1: businesslogica in de database stoppen
Het begint onschuldig. Een stored procedure hier, een trigger daar. De database is snel, de logica werkt, en de ontwikkelaar hoeft minder code te schrijven. Maar na twee jaar zit de businesslogica verspreid over tientallen procedures die onderling afhankelijk zijn. Een prijsregel aanpassen betekent uitzoeken welke triggers je raakt. Een tweede applicatie aansluiten op dezelfde database is onmogelijk zonder die logica te dupliceren of te breken. Schaalbaarheid in maatwerksoftware begint bij een heldere scheiding: de database slaat data op, de applicatie beslist. Zodra die grens vervaagt, betaal je dat later terug in weken herbouwwerk per wijziging.
Architectuurkeuze 2: alles synchroon koppelen zonder event-driven patronen
In een klein systeem met tien gebruikers is een directe, synchrone koppeling tussen modules prima. Systeem A roept systeem B aan, wacht op een antwoord, en gaat verder. Dat werkt tot het volume groeit. Bij honderd gelijktijdige gebruikers of een koppeling met een extern systeem dat soms traag reageert, worden die wachttijden zichtbaar. Eén trage schakel legt de hele keten plat. Event-driven patronen, waarbij een module een bericht plaatst en de ontvangende module dat op zijn eigen tempo verwerkt, zijn niet altijd nodig. Maar als je weet dat het systeem moet groeien in volume of aantal koppelingen, is het ontbreken van die laag een architectuurkeuze die je terugbetaalt. Het toevoegen achteraf kost doorgaans meer dan het van tevoren meenemen.
Architectuurkeuze 3: onduidelijke domeingrens in de maatwerksoftware architectuur
De derde keuze is de lastigste om te zien, omdat hij niet in de code zit maar in de structuur van het systeem. Als een ordermodule ook voorraadinformatie bijhoudt, klantgegevens schrijft en factuurregels aanmaakt, is er geen duidelijke domeingrens. Alles hangt aan alles vast. Dat voelt efficiënt in een klein team, maar zodra je een tweede team toevoegt, een module apart wil schalen, of een nieuwe functionaliteit wil bouwen, kost elke wijziging een analyse van het hele systeem. Duidelijke domeingrenzen, waarbij elke module één verantwoordelijkheid heeft en via expliciete interfaces communiceert, maken het verschil tussen software die meegroeit en software die een plafond heeft.
Wanneer is een 'te kleine' architectuur acceptabel?
Niet elke situatie vraagt om een volledig gedistribueerde, event-driven architectuur van dag één. Als je een intern proces valideert, een nieuwe markt test, of een klein team bedient dat stabiel blijft, is een eenvoudigere opzet vaak de betere keuze. Complexiteit heeft een prijs: meer infrastructuur, meer kennis nodig, meer overhead in het bouwen. De vraag is niet of je architectuur perfect is, maar of je de schuld die je aangaat kunt overzien. Technische schuld is acceptabel als je weet wat je inruilt en wanneer je van plan bent het te vereffenen. Het wordt een probleem als de schuld verborgen blijft: als niemand in het team weet dat de businesslogica in de database zit, dat er geen domeingrens is, of dat elke koppeling synchroon is. Dan betaal je dubbel: eenmaal bij het bouwen van de nieuwe functionaliteit die niet past, en nogmaals bij het opruimen van wat er al stond.
Wanneer betaal je de architectuurschuld dubbel?
Er zijn drie momenten waarop de schuld uit de hand loopt. Het eerste is een overname of fusie, waarbij twee systemen samen moeten werken die elk hun eigen verborgen logica hebben. Het tweede is het moment van verplichte externe koppeling, bijvoorbeeld een nieuwe regelgeving of een klant die een API-integratie eist. Het derde is de schalingspiek: een nieuw contract, een seizoenspiek, of plotselinge groei die het systeem niet had verwacht. Op elk van die momenten sta je niet alleen voor de vraag hoe je de nieuwe functionaliteit bouwt, maar ook voor het ontwarren van wat er al is. Een architectuur die op dag één meeschaalt, vraagt meer tijd vooraf. Maar die investering betaalt zich terug op precies de momenten dat je het minste tijd hebt voor herstelwerk.
