Schaalbare Microservices Bouwen: Echte Patterns uit de Praktijk
Engineering Architectuur 15 december 2025

Schaalbare Microservices Bouwen: Echte Patterns uit de Praktijk

Een praktische kijk op microservices architectuur - de patterns die echt werken, de valkuilen die ons beetpakten, en waarom een monoliet soms zo slecht nog niet is.

E
Engineering Team
Senior Solutions Architects
14 min lezen

Het Echte Probleem

Toen we voor het eerst naar dit financiรซle diensten platform keken, had het die bekende geur. Een monoliet die 50.000 dagelijkse gebruikers bediende, deployments die nachtelijke onderhoudsvensters vereisten, en een codebase waar het aanraken van module A op een of andere manier module Z kapot maakte.

Het bedrijf wilde lagere infrastructuurkosten, meer ontwikkelflexibiliteit, snellere time-to-market, en de mogelijkheid om individuele features onafhankelijk te schalen. Klassiek - maar de duivel zit in de details.

Microservices: Hype vs Realiteit

Laten we eerlijk zijn - microservices lossen specifieke problemen op, niet alle problemen. Dit is wat onze beslissing echt dreef:

  • Deployment onafhankelijkheid - de betaalmodule shippen zonder user auth aan te raken
  • Blast radius containment - wanneer (niet als) dingen kapot gaan, gaan ze klein kapot
  • Polyglotte persistentie - Postgres voor transacties, Redis voor sessies, MongoDB voor documenten
  • Team ownership - duidelijke grenzen betekenen duidelijke verantwoordelijkheid
  • Gerichte scaling - de zoekservice schalen tijdens piek, niet de hele app

Architectuur Deep Dive

We bouwden op Domain-Driven Design, maar niet de academische versie. Bounded contexts ontstonden uit echte teamgesprekken, niet uit whiteboard oefeningen. Onze principes:

  • Aggregate grenzen definiรซren service grenzen - als het รฉรฉn transactie is, is het รฉรฉn service
  • Events boven sync calls - choreografie verslaat orchestratie in de meeste gevallen
  • API contracten als first-class citizens - breek het contract, breek de build
  • Shared-nothing architectuur - elke service bezit zijn data, punt
  • Observability is niet optioneel - als je het niet kunt tracen, ship het niet

De Stack (En Waarom)

Elke tool keuze was een tradeoff. Hier is waar we op uitkwamen:

text
Infrastructure:
โ”œโ”€โ”€ Kubernetes (EKS) โ†’ Declaratieve deployments, self-healing
โ”œโ”€โ”€ Istio service mesh โ†’ mTLS, traffic shaping, circuit breaking
โ”œโ”€โ”€ Kong API Gateway โ†’ Rate limiting, auth, request transformatie
โ”‚
Messaging:
โ”œโ”€โ”€ Kafka โ†’ Event backbone, 7-dagen retention
โ”œโ”€โ”€ Redis Streams โ†’ Lichtgewicht pub/sub, efemere data
โ”‚
Data Layer:
โ”œโ”€โ”€ PostgreSQL โ†’ ACID transacties, JSONB voor flexibiliteit
โ”œโ”€โ”€ MongoDB โ†’ Document store voor audit logs, activity feeds
โ”œโ”€โ”€ Redis Cluster โ†’ Session store, gedistribueerde caching
โ”œโ”€โ”€ Elasticsearch โ†’ Full-text search, log aggregatie
โ”‚
Observability:
โ”œโ”€โ”€ OpenTelemetry โ†’ Vendor-agnostische instrumentatie
โ”œโ”€โ”€ Prometheus + Thanos โ†’ Metrics met lange termijn opslag
โ”œโ”€โ”€ Grafana โ†’ Dashboards, alerting
โ”œโ”€โ”€ Jaeger โ†’ Distributed tracing
โ”‚
CI/CD:
โ”œโ”€โ”€ GitLab CI โ†’ Build, test, security scanning
โ”œโ”€โ”€ ArgoCD โ†’ GitOps deployments
โ”œโ”€โ”€ Sealed Secrets โ†’ K8s-native secret management

Patterns Die Ons Redden

Theorie is leuk. Hier is wat ons echt uit de problemen hield:

**Transactional Outbox** - In plaats van dual-writes (database + message broker), schrijven we events naar een outbox tabel in dezelfde transactie. Een apart proces publiceert ze. Atomisch. Betrouwbaar. Geen nachtmerries met gedistribueerde transacties.

**Event Sourcing (waar het telt)** - Voor betaalflows en audit-kritische paden slaan we events op, geen state. Elke mutatie is een onveranderlijk event. Productie problemen debuggen door exacte sequenties af te spelen. Compliance teams zijn er dol op.

**CQRS met Projecties** - Write models geoptimaliseerd voor validatie, read models geoptimaliseerd voor queries. Eventual consistency is prima voor read views. Het reporting team krijgt hun gedenormaliseerde tabellen zonder het write path te vervuilen.

**Saga Orchestration** - Langlopende business processen (onboarding, payment settlement) als expliciete state machines. Compenserende transacties bij falen. Geen verweesde partial states.

**Circuit Breaker + Bulkhead** - Hystrix is dood, maar de patterns niet. Resilience4j handelt circuit breaking, rate limiting en retry met backoff. Aparte thread pools voor externe integraties.

De Betaalflow: Echte Architectuur

Zo beweegt echt geld door het systeem:

text
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”      โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”      โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ API Gateway โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”‚  Payment    โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”‚   Fraud     โ”‚
โ”‚   (Kong)    โ”‚ gRPC โ”‚  Service    โ”‚ Eventโ”‚  Detection  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜      โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”˜      โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                            โ”‚                    โ”‚
                     PaymentInitiated      FraudCheckCompleted
                            โ”‚                    โ”‚
                            โ–ผ                    โ–ผ
                     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”      โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                     โ”‚   Outbox    โ”‚      โ”‚    Risk     โ”‚
                     โ”‚   Table     โ”‚      โ”‚   Scoring   โ”‚
                     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”˜      โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                            โ”‚                    โ”‚
                     Debezium CDC           RiskAssessed
                            โ”‚                    โ”‚
                            โ–ผ                    โ–ผ
                     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                     โ”‚         Kafka Topics            โ”‚
                     โ”‚  payments.initiated             โ”‚
                     โ”‚  fraud.checked                  โ”‚
                     โ”‚  risk.assessed                  โ”‚
                     โ”‚  payments.completed             โ”‚
                     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                    โ”‚
            โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
            โ–ผ                       โ–ผ                       โ–ผ
     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”         โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”         โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
     โ”‚   Ledger    โ”‚         โ”‚   Order     โ”‚         โ”‚Notification โ”‚
     โ”‚   Service   โ”‚         โ”‚   Service   โ”‚         โ”‚   Service   โ”‚
     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜         โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜         โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Test Strategie Die Echt Werkt

Vergeet de testing piramide even. In gedistribueerde systemen heb je nodig:

  • Contract tests (Pact) - Services praten met stubs, niet echte dependencies. Contracten breken in CI, niet productie
  • Consumer-driven contracts - Consumers definiรซren wat ze nodig hebben, providers bewijzen dat ze leveren
  • Chaos testing (Chaos Monkey, Litmus) - Willekeurig pods killen. Latency injecteren. Resilience bewijzen
  • Synthetic monitoring - Continue productie probes voor kritieke user journeys
  • Load testing als validatie - We valideerden dat de architectuur 80x het originele verkeer aankon door rigoureuze load tests voor lancering
  • Canary deployments - 1% verkeer naar nieuwe versies, automatische rollback bij error spike

Wat Er Echt Gebeurde

In het begin focusten we op het decomponeren van de monoliet - naden identificeren, het oude systeem service voor service wurgen. In het begin was het ruw. Gedistribueerde debugging skills ontbraken, traces waren incompleet, en netwerk partities legden consistentie bugs bloot.

Na enkele maanden klikte het. Teams bezaten hun services end-to-end. Deployments werden non-events. Het platform engineering team had genoeg golden paths gebouwd dat een nieuwe service opzetten uren duurde, geen weken.

Toen de tijd verstreek en de architectuur rijpte, spraken de resultaten voor zich:

  • Response tijden daalden van 850ms p99 naar onder 120ms p99
  • Zero-downtime deployments - onderhoudsvensters werden een herinnering
  • Infrastructuurkosten 35% lager ondanks hoger verkeer
  • Deployment frequentie: van maandelijks naar 50+ dagelijkse deploys
  • Gemiddelde hersteltijd: onder 5 minuten voor de meeste incidenten

De Harde Lessen

Niet alles ging soepel. Hier is wat pijn deed:

**Eventual consistency is een feature, geen bug** - Maar leg dat uit aan de PM die zich afvraagt waarom het dashboard verouderde data toont. Ontwerp ervoor. Communiceer het.

**Distributed tracing of de dood** - Zonder correlation IDs en correcte trace context propagatie is debuggen archeologie. OpenTelemetry auto-instrumentatie is je vriend.

**Schema evolutie is moeilijk** - Avro met schema registry. Alleen backwards-compatible wijzigingen. Breaking changes vereisen een nieuw topic.

**Kubernetes is een besturingssysteem** - Vecht er niet tegen. Leer het. Resource limits, liveness probes, pod disruption budgets - ze bestaan om redenen.

**Platform team is niet onderhandelbaar** - Iemand moet de infrastructuur abstracties bezitten. Anders vindt elk team het wiel opnieuw uit.

Wanneer GEEN Microservices

Eerlijk gezegd - microservices zijn duur. Overweeg alternatieven als:

  • Je team is klein - coรถrdinatie overhead doodt snelheid
  • Domein grenzen zijn onduidelijk - je tekent ze verkeerd en lijdt migratie pijn
  • Je hebt geen platform engineering capaciteit - infrastructuur complexiteit explodeert
  • Latency eisen zijn extreem - netwerk hops tellen op
  • Je monoliet heeft gewoon betere modularisatie nodig - probeer eerst een modulaire monoliet

Takeaways

Aan het eind van deze reis hadden we een platform dat continu deployede, on-demand schaalden, en teams echte ownership gaf. Het bedrijf kreeg wat ze vroegen: lagere kosten, snellere delivery, en de flexibiliteit om te evolueren.

Was het het waard? Voor deze schaal en deze eisen, absoluut. Maar we begonnen met een modulaire monoliet en extracten alleen services toen de pijn echt was.

Denk je aan dit soort transformatie? Begin met het probleem, niet de oplossing.

Key Takeaways

Microservices architectuur gaat niet over trends volgen - het gaat over het oplossen van specifieke schaling en organisatie uitdagingen. De patterns die we behandeld hebben (transactional outbox, event sourcing, CQRS, saga orchestration) zijn geen theoretische oefeningen; het zijn beproefde oplossingen voor echte gedistribueerde systeem problemen.

We valideerden dat de architectuur 80x het originele verkeer kon dragen door uitgebreide load testing. Deployments gingen van maandelijkse events naar non-events die tientallen keren per dag gebeuren. Dat is de payoff als je de fundamentals goed doet.

Heb je architectuur uitdagingen waarmee je worstelt? Laten we praten over patterns.

#microservices #kubernetes #docker #scalability #devops #cloud-native #event-sourcing #cqrs #ddd
E

Engineering Team

Senior Solutions Architects

We bouwen gedistribueerde systemen sinds voordat 'microservices' een term was. Onze littekens vertellen verhalen.