Wie een monoliet afbreekt, raakt meer dan code. Architectuur is organisatie, verantwoordelijkheden, tooling, deploymentritme, kostenbewustzijn en zelfs werving. De technische keuzes vallen vaak mee, het echte werk zit in de interfaces tussen teams, systemen en processen. Zolang die interfaces niet helder zijn, versplinter je een monoliet in losse stukjes complexiteit, niet in microservices.
Ik heb migraties gezien waar teams in zes maanden hun time to market halveerden en incidenten met 40 procent terugbrachten. Ik heb ook trajecten meegemaakt waarin de factuur van de cloudleverancier verdubbelde, terwijl de releasefrequentie stagneerde. Het verschil zat niet in een wonderframework, maar in discipline rondom grenzen, data en eigenaarschap. In deze gids leg ik uit wat helpt, wat schaadt en welke keuzes je echt niet kunt uitstellen.
Waar microservices wel en niet voor werken
Microservices leveren vooral waarde wanneer onafhankelijk veranderen belangrijker is dan het per request snelste pad. Als je productportfolio vaak wijzigt, als je teams meerdere releases per week willen doen, of als je verschillende technologieën wilt combineren zonder lock-in, dan helpen kleinere, losjes gekoppelde services. Je betaalt voor die flexibiliteit met extra netwerkhops, complexere debugging en meer werk in pipeline en observability.
Voor stabiele, sterk gecorreleerde functionaliteit zonder harde schaalproblemen is een goed gesneden modulair monoliet nog steeds een sterke optie. Denk aan een financieel kernsysteem met intensieve transacties en weinig behoefte aan frequent scheiden van releasemomenten. Veel organisaties onderschatten hoe ver je komt met duidelijke modulegrenzen, interne interfaces en een solide teststrategie. Een modulair monoliet kan zelfs een tussenstap zijn om grenzen scherp te krijgen vóórdat je fysiek services splitst.
Een vuistregel die ik hanteer: als twee onderdelen in 80 procent van de gevallen samen veranderen, splits ze niet. Als een domein op zichzelf kan falen zonder een klant te blokkeren, en als het team er zelfstandig over kan deployen en on call kan staan, dan is het een kandidaat voor een losse service.
Organisatie-eigenaarschap en teamtopologie
Architectuur volgt teamstructuur. Zonder duidelijke teamgrenzen veranderen microservices in onduidelijkheden. Een team dat een service beheert, is verantwoordelijk voor code, runtime, incidentafhandeling en kosten. Dat klinkt als DevOps, maar vraagt ook om platformondersteuning: security defaults, paved roads voor CI/CD, observability standaarden en een mature cloudlandingzone.
Teamgrootte is cruciaal. Met meer dan acht mensen in een team verlies je snelheid, met minder dan vier verlies je veerkracht. Twee pizza teams werken in de praktijk alleen als je de rest faciliteert: automatische provisioning, secret management, en permissions die zonder ticket kunnen worden aangepast. Als teams toegang nodig hebben tot drie andere teams om een testomgeving te krijgen, krijg je wachttijden die elke microservicewinst tenietdoen.
Bij internationale schaal, of wanneer je Nearshore AI Development in je portfolio opneemt, helpt het om platformcapaciteiten te centraliseren in een klein, ervaren team. Dat team levert self service componenten, geen handwerk. Zo houd je variatie waar het loont, en standaardisatie waar het moet.
Domeingrenzen scherper snijden dan code
De eerste fout bij migraties is grenzen trekken langs technische lagen - bijvoorbeeld een user service, een order service en een payment service met gedeelde databasetabellen. Daarmee verplaats je tabelkoppelingen naar API calls, zonder duidelijke domeinverantwoordelijkheid. Bounded contexts uit Domain Driven Design geven meer houvast. Splits functionaliteit op het niveau van taal en verantwoordelijkheid, niet op het niveau van tabel of framework.
Een eenvoudige test: kun je het domein van een service in twee zinnen uitleggen aan iemand van support? Als dat niet lukt, is de snede te vaag. Voor een retailklant hebben we bijvoorbeeld Fulfillment afgescheiden van Checkout. Fulfillment gaat over voorraad, picking en verzending. Checkout gaat over winkelmand, prijzen, promoties en betaling. Beide teams hadden elk hun eigen datamodel en incidentrotatie. Nauwe samenwerking bleef nodig, maar het eigenaarschap was helder.
Gebruik de strangler fig approach als je de monoliet niet in één keer kunt vervangen. Leid verkeer stap voor stap om, voor één functionaliteit tegelijk. Elk omgeleid pad is een toetsmoment: meten, stabiliseren, pas dan verder. Het lijkt trager, maar je wint omdat je risico's inperkt en regressies sneller vindt.
Transacties, consistentie en geld dat niet verdwijnt
Monolieten leunen vaak op ACID transacties over meerdere tabellen. In microservices heb je die luxe niet. Je gaat naar eventual consistency met compenserende acties. Dat hoeft niet eng te zijn, mits je het expliciet ontwerpt. Gebruik slookup scenario’s om te bepalen wanneer je sterke consistentie per se nodig hebt, bijvoorbeeld voor een bankrekeningboeking, en wanneer een tijdelijke inconsistentie aanvaardbaar is, zoals het later synchroniseren van een loyalty score.
Een saga patroon helpt om langere processen te orkestreren. Je kiest tussen choreography, waar services events van elkaar consumeren, en orchestration, waar een aparte coördinator de stappen aanstuurt. Beide werken, de keuze hangt af van zichtbaarheid en foutafhandeling. Als je drie tot vijf stappen hebt en strakke compensatie nodig is, levert een orkestrator vaak meer grip en betere observability. Bij tien plus stappen met veel varianten kan choreography flexibeler zijn, zolang je idempotency en timeouts strak beheert.
Idempotency is niet optioneel. Elke muterende call moet veilig herhaalbaar zijn. Gebruik idempotency keys, natural keys waar mogelijk, en pas retry- en backoffstrategieën aan op jouw timeouts. Reken met network jitter en packet loss. Binnen één datacenter is een service hop gemiddeld 1 tot 2 milliseconden, over regio’s 30 tot 80 milliseconden. Tien hops en twee retries per hop tikken hard aan als je latentie-eisen krap zijn.
Data-eigendom en integratiemodellen
Een microservice beheert zijn eigen data en stelt die bloot via een API of events. Geen gedeelde tabellen. Wil je een integraal beeld opvragen, dan pull je via API of bouw je een leesmodel. Voor analytische doeleinden werkt change data capture goed: stream databasewijzigingen naar een analytics store en voorkom dat je OLTP services belast met zware queries.
Dual writes naar twee systemen tegelijk lijken aantrekkelijk, maar veroorzaken snel inconsistentie. Als je niet om dual writes heen kunt, maak de flow expliciet: eerst een lokale commit, dan een betrouwbaar event dat downstream systemen verwerkt. Meet je outbox latency, log correlation ids, en bewaak je dead letter queues structureel.
Event sourcing trekt de lijn door en maakt de eventstroom zelf bron van waarheid. Dat geeft auditability en flexibiliteit, maar verhoogt de leercurve en maakt query’s lastiger. Mijn ervaring: alleen doen waar het een duidelijk voordeel oplevert, bijvoorbeeld in financiële domeinen Development Team of taming complex state machines.
Observability: kijken voordat je reageert
Zonder zicht geen snelheid. Loggen, metrics en tracing zijn geen kostenpost, maar een productiviteitshefboom. Richt een uniforme correlatie in met trace ids door de hele call chain. Maak SLO’s die aansluiten bij gebruikerservaring, niet bij technische proxies. Een 99.9 percentiel latency van 400 milliseconden zegt meer over je winkelmand dan een gemiddelde van 50 milliseconden.
Zorg dat elk team dashboards heeft die ze dagelijks gebruiken. Een apart war room dashboard dat alleen bij incidenten open gaat, verliest snel actualiteit. Alert alleen op signalen die actie vereisen. Niets sloopt een on call cultuur zo snel als valse positieven. In één organisatie hebben we het aantal alerts per week teruggebracht van 150 naar 20 door ruisfilters en betere SLO’s. De MTTR halveerde in twee sprints.
Trace sampling is een valkuil. Volledige sampling in productie kan duur zijn, maar te agressieve sampling verbergt net de zeldzame problemen. Begin conservatief, bijvoorbeeld 10 tot 20 procent, en verhoog tijdelijk bij incidenten. Investeer in span naming conventies en standaard metadata zoals tenant, versie en region.
CI/CD en platformafspraken
Microservices zonder volwassen CI/CD zijn micro-problemen. Elke service moet een eenduidige pipeline hebben met build, test, security checks, image signing en deploy met progressive delivery. Feature flags en canary releases geven speling om fouten op te vangen zonder rollbacks. Blue green kan, maar schaalt minder goed bij tientallen services.
Automatisering stopt niet bij deployment. Infra as code, secrets rotatie, policy as code en cost tagging horen erbij. Platformteams binnen DevOps & Cloud Services leveren golden paths met opinionated defaults. Dependencies en libraries moeten versieerbaar en vervangbaar zijn. Als je updates van een standaardbase image niet binnen een week door alle services kunt duwen, wordt patchen een helling zonder eind.
Semver helpt bij API’s, maar backward compatibility is het echte werk. Deprecation policies zijn alleen geloofwaardig als je tooling bouwt die gebruik van verouderde endpoints detecteert en tijdig waarschuwt. Houd de afbouw horizon kort - Swift meestal 3 tot 6 maanden - en help consumenten met migratievoorbeelden.
Kosten, performance en schaal: meten is sturen
Microservices splitsen een call op in meerdere netwerkrondes. Waar de monoliet 5 milliseconden computation en 1 milliseconde IO had, kan de keten met vijf services oplopen tot 30 tot 80 milliseconden voordat je extra logica meerekent. Dat is prima als het product het aankan, maar je moet keuzes maken. Vermijd chatty interfaces, ontwerp coarse grained endpoints en pas bulkoperaties toe waar zinvol.
Cold starts in serverless omgevingen lijken vaak de boosdoener, maar in veel trajecten zat de grootste vertraging in DNS timeouts of TLS handshakes door verkeerde connection pooling. Meet handshake ratios, reuse rates en keep alive instellingen. Zet timeouts op elk niveau, en maak ze korter dan de upstreampolicy om rare staarten te voorkomen.
Kosten lopen op door duplicatie, netwerk en observability. Toch zijn besparingen haalbaar met autoscaling op werkelijke load, spot instances waar risico aanvaardbaar is, en door queues te dimensioneren op pieken in plaats van gemiddelden. Houd cardinaliteit van metrics laag. Tien labelwaarden meer kunnen de factuur verdubbelen bij hoge time series aantallen.
Beveiliging als standaard, niet als project
Zero trust tussen services is geen luxe. mTLS, identity per workload, en centrale policy enforcement reduceren later veel pijn. Secrets horen in een dedicated secret manager, niet in environment variabelen of CI logs. Rotate tokens automatisch en verleen toegang via short lived credentials.
Minimaliseer data exposure. Een Order service hoeft geen e mail van een klant te zien om een status te updaten. Scherm PII door model splitsing en tokenisatie. Bouw data egress regels die voorkomen dat een service per ongeluk grote datasets uitserveert naar de buitenwereld. Auditeer wie bij welke logs kan, want logs bevatten vaak meer gevoelige informatie dan de primaire database.
Governance zonder stroperigheid
Te strakke controle doodt snelheid, te losse standaarden leiden tot drift. Werk met lichte, dwingende conventies: naming, API style guide, error codes, typische timeouts, en een default circuit breaker strategy. Leg niet elk detail vast, maar zorg voor voorbeelden en libraries die de standaard makkelijk maken.
Documentatie moet dichtbij de code leven, bijvoorbeeld via OpenAPI definities uit de pipeline. Reviews gaan over API grenzen en backward compatibility, niet over spaties en haakjes. Kies één tot twee serieuze standaarden voor messaging en API’s en blijf daarbinnen, tenzij er een hard voordeel is van iets anders. Variatie is kostbaar.
Veelvoorkomende valkuilen en wat je ertegen doet
- Granulariteit verwarren met kwaliteit: te kleine services verhogen cognitieve last. Snijd op teamverantwoordelijkheid en veranderfrequentie, niet op technisch detail. Gedeelde databases: korte termijn snel, lange termijn duur. Forceer service eigen datamodellen en lever events voor integratie. Observability onderschatten: zonder tracing en SLO’s kun je niet betrouwbaar deployen. Investeer vroeg in metrics, logs en trace propageren. Onrealistische latentie en timeouts: ontwerp op ketens, niet op individuele services. Pas bulk endpoints toe en vermijd chatty patronen. Platform als handwerk: zonder self service en opinionated defaults verstik je in tickets. Bouw paved roads voor CI/CD, security en infra.
Een praktische routekaart van monoliet naar microservices
- Start met een modulair monoliet en maak domeingrenzen expliciet. Meet koppelingen en veranderfrequentie. Kies pas daarna de eerste te isoleren capability. Bouw het platformpad: CI/CD, observability, secrets, identity en cost tagging. Zonder dit fundament worden alle wins verdampt door operationele frictie. Kies één end to end flow voor de strangler fig aanpak, bijvoorbeeld checkout. Splits één service uit, routeer verkeer, monitor, stabiliseer, ga pas daarna naar de volgende. Richt SLO’s, runbooks en on call in per service. Laat teams verantwoordelijkheid nemen voor incidenten en kosten. Maak rotaties haalbaar met goede tooling. Ruim legacy op zodra verkeer stabiel is omgeleid. Verwijder dode code, sluit databasepaden af en archiveer alleen wat je aantoonbaar nodig hebt.
Een veldnotitie: checkout zonder hoofdpijn
Bij een e commerce speler met 8 miljoen maandelijkse sessies draaide checkout in een verouderde monoliet. Marketing wilde sneller experimenteren met bundels en promoties, finance vroeg om strakkere reconciliatie. Het team koos niet direct voor een microserviceorgie, maar bracht eerst structuur aan: pricing en promotions als expliciete modules, payment adapters los in code en tests die flows end to end simuleerden.
Pas daarna is één capability uitgehaald: de payment authorization. Reden: duidelijke grenzen, beperkt datamodel, extern afhankelijk van PSP’s. Het team bouwde een Payment service met eigen store, event outbox en duidelijke idempotency. Event schema’s werden via een klein library gedeeld. De latentie nam 12 tot 18 milliseconden extra in beslag, maar de betrouwbaarheid steeg. Refunds liepen via een saga die compenserend werkte als PSP timeouts optraden.
Met die ervaring is Promotions losgetrokken. Dat bleek lastiger dan gedacht door gedeelde datavisie op customer segments. De oplossing zat niet in techniek, maar in het domein: segments zijn eigendom van CRM, promotions consumeert alleen anonieme segmentflags. De koppeling via events verminderde PII exposure. Marketing kon binnen een maand AB tests met nieuwe promotietypen draaien, iets wat eerder weken kostte.
Belangrijk detail: de hostingkosten stegen aanvankelijk met 30 procent door overprovisioning en te rijke metrics. Door autoscaling op request queues en het terugbrengen van high cardinality labels, daalden de kosten na twee sprints onder het oorspronkelijke niveau, ondanks extra componenten. De MTTR ging van 90 naar 35 minuten, vooral door betere tracing en heldere eigenaarschap.
Rekrutering en capaciteit: mensen maken de migratie
Technisch talent bepaalt het tempo. Microservices vragen andere vaardigheden dan klassieke monolieten: distributed systems denken, productiegericht werken, en comfort met tooling. IT Recruitment moet dus verder kijken dan frameworks, en testen op domeinredenering, incidentervaring en security hygiene. Een kandidaat die uitlegt hoe hij idempotency afdwingt en timeouts afstemt over ketens, voorkomt maanden gedoe.
Nearshore teams kunnen snelheid geven, zeker bij componenten die duidelijk omlijnd zijn - bijvoorbeeld een reporting pipeline, een integratieadapter of een AI module die fraudedetectie ondersteunt. Let wel op overlappende werkuren en zorg voor gezamenlijke on call normen. Ik heb goede resultaten gezien wanneer producteigenaars twee keer per week refinement doen met nearshore teams, en wanneer platformcomponenten door een klein, ervaren kernteam in huis blijven.
Koppel rekrutering aan je Digital Transformation roadmap. Als je het komende jaar vooral data exits en events gaat bouwen, zoek profielen met Kafka of vergelijkbaar, CDC ervaring en security basics. Als je naar Kubernetes gaat, haal mensen binnen die niet alleen clusters draaien, maar ook netwerk, policy en cost control begrijpen. Voeg coaching toe aan contracten van externe specialisten, zodat kennis blijft als mensen weggaan.
Wanneer stoppen met splitsen
Services worden niet automatisch beter door kleiner te worden. Te kleine services leiden tot context switching, teveel deploys en gebroken ketens. Kijk naar cognitieve last: kan het team zonder document te lezen een incident in die service oplossen in redelijke tijd? Als het antwoord nee is, zijn de grenzen onnatuurlijk of de service te klein.
Kijk ook naar veranderfrequentie. Als twee services bijna altijd samen meeveranderen, horen ze bij elkaar. Combineer ze of maak C# een shared module die sneller mee versieert. Een monorepo kan ongewenst aanvoelen, maar biedt vaak praktische voordelen voor gecoördineerde releases met behoud van scheiding in runtime. Het gaat om onafhankelijk deployen, niet per se om onafhankelijk committen.
Technologiekeuzes met beleid
Frameworks lossen geen personeels- of procesproblemen op. Kies technologie op basis van operationele volwassenheid en aansluiting bij je DevOps & Cloud Services fundament. Een service mesh kan mTLS, retries en circuit breaking standaardiseren, maar brengt ook complexiteit. Als je team nog worstelt met eenvoudige tracing, is een mesh waarschijnlijk te vroeg.
Evenzeer geldt: kies bewust tussen REST en event driven. REST is rechttoe rechtaan voor request response patronen. Events werken beter voor notify en async flows. Mixing kan, maar definieer per use case het dominante patroon en ga niet voor ieder wissewasje events toevoegen. Overdaad aan topics en schemadefinities is een onderhoudsstorm die zelden rendeert.
Voor databases geldt: polyglot persistence is krachtig, maar duur in beheer. Beperk variatie tot echte voordelen - bijvoorbeeld een document store voor flexibele catalogi en een relationele database voor transacties. Houd het aantal technologieën per team laag, en investeer in goede backup en restore scenario’s. Test disaster recovery niet op papier, maar echt, met data en tijdsdruk.
Beproefde werkafspraken die het verschil maken
Een paar praktische afspraken leveren onevenredig veel rust op. Voor elke service: één duidelijke owner, SLO’s op latency en fouten, runbooks met vier scenario’s - performance regressie, database connectiviteit, externe afhankelijkheid stuk, en verkeerde configuratie. Voor elke breaking API change: migratiegids en een timeframe. Voor elke queue: DLQ beleid en een plan om te draineren zonder data te verliezen.
Leg een changelog naast je monitoring. Als je grafiek een sprong toont, wil je in één oogopslag zien welke release, feature flag of infra wijziging ermee samenvalt. Automatiseer bovendien je rollbacks. Mensen zijn traag en voorzichtig, scripts zijn snel en consequent. Doe chaos drills, klein en gecontroleerd. Je leert er sneller van dan van tien post mortems.
Tot slot, maak kosten zichtbaar in de backlog. Als een feature structureel 500 euro per dag extra kost in compute of egress, moet dat in de afweging naast de businesswaarde. Cost per request of per tenant als metric in je service helpt teams scherpe keuzes te maken. Het is een wezenlijk onderdeel van volwassen Software Development.
Slotgedachte
De stap van monoliet naar microservices is geen religie en geen knop. Het is een reeks keuzes die je organisatie vormgeven. Wie de eerste services pas afscheurt nadat de domeinen scherp zijn, wie platform en observability als fundament behandelt, en wie eigenaarschap serieus organiseert, plukt de vruchten: sneller leveren met minder stress. Wie te vroeg splits, zonder grenzen en zonder tooling, verruilt één groot probleem voor vijftig kleine. Het verschil zit zelden in techniek alleen, wel in consistent vakmanschap en de moed om te meten, leren en bij te sturen.