Beispiel C: Trainingsplattform in der Luftfahrt

  • Problem: Komplexes Kurs- und Berechtigungsmodell, umfangreiche Audit-Trails, On-Prem- oder private Cloud-Deployment; lange Lebensdauer.
  • Architektur:
  • Modulare Monolithen mit klaren Modulen: Identity & Roles, Curriculum, Simulator Sessions, Compliance, Reporting.
  • Event-Log intern für Audit, exportierbar; Berichte generiert asynchron, aber in-prozess getriggert.
  • API-Layer stabil, aber nach außen nur ein Endpunkt (Gateway) – geringe Angriffsfläche, einfache Härtung.
  • Warum Monolith? Compliance-getriebene Konsistenz, Planbarkeit von Releases, minimierte Betriebsvariabilität.

5) Operative Vorteile im On-Prem-Setup

  • Ein Artefakt, eine Lieferkette: Ein signiertes Paket mit SBOM, reproduzierbar gebaut. Weniger Angriffspunkte, einfachere Audits.
  • Rollback und Datenmigrationen: Migrationsskripte transaktional, idempotent; die Kopplung an ein Artefakt reduziert Komplexität bei Vor-Ort-Rollbacks erheblich.
  • Observability ohne Service-Zoo: Interne Komponenten emittieren Traces mit Komponentenschlüsseln, Logs strukturiert mit Korrelationen über Event-IDs. Ein Agent, ein Ziel.
  • Netzwerk-Härtung: Keine Service Discovery, kein Service Mesh, keine dynamischen Sidecars, die in air-gapped Netzen ohnehin schwer zu betreiben sind. TLS innerhalb eines Prozesses irrelevant; zwischen wenigen Prozessen mTLS mit eigener PKI machbar.
  • Ressourcenökonomie: Ein Prozess kann Speicher- und Objektpools effizient teilen. Kein serielles (De-)Serialisieren zwischen Services, keine gRPC-Overheads für Intra-Domain-Kommunikation.

6) Leistungsprofil und Skalierung eines Monolithen

Skalierung ist nicht exklusiv ein Microservice-Feature. Typische Muster:

  • Vertikale Skalierung: Realtime-Pfade in C++ mit lock-armen Queues, NUMA-Awareness, Pinning. Kritische Hot Paths sind im Monolith leichter zu profilieren und in einem Adressraum zu optimieren.
  • Horizontale Skalierung: Mehrere Instanzen des Monolithen hinter einem simplen TCP/HTTP-Loadbalancer. Externen Zustand in einer robusten Datenbank oder einem dedizierten State Store (z. B. Redis) halten. Session-Management entkoppeln oder Sticky Sessions einsetzen.
  • Interne Parallelisierung: Worker-Pools pro Modul, Backpressure über interne Queues. Asynchronität ist nicht an Netzgrenzen gebunden.
  • Read/Write-Skalierung: CQRS intern anwenden – getrennte Lesemodelle/Materialized Views für Dashboards, ohne das Domänenmodell aufzublähen.
  • Batch-Heavy Workloads: Dedizierte Worker-Prozesse (innerhalb desselben Deployments) für ETL/Analytik; Start/Stop steuerbar, Ressourcen limitiert, ohne separate Deploy-Pipelines.

Wann Microservices in puncto Skalierung dennoch gewinnen:

  • Wenn einzelne Domänenkomponenten echt unterschiedliche Lastcharakteristika und Lebenszyklen haben, die mit separatem Deployment erheblich günstiger zu betreiben sind (z. B. stark variable, extern konsumierte Public API vs. stabile interne Planung).
  • Wenn unabhängige Teams mit klaren, stabilen Boundaries autonom liefern müssen.

7) Grenzen des Monolithen und Exit-Strategie ohne Big-Bang

Symptome, dass eine Extraktion sinnvoll wird:

  • Ein Modul hat andere Verfügbarkeits- und Skalierungsziele als der Rest (z. B. extern exponierte API mit spiky Traffic).
  • Sicherheitsgründe erfordern Isolation (z. B. Ausführung untrusted Drittanbieterlogik, regulatorisch getrennte Datenbereiche).
  • Release-Kadenz divergiert massiv (z. B. monatliche Compliance-Releases vs. tägliche Modellupdates).

Migrationspfad:

  • Strangler-Pattern: Zu extrahierende Capability durch einen internen Adapter kapseln. Dann die Implementierung über eine Remote-Schnittstelle ersetzen, ohne die restliche Codebasis zu berühren.
  • Contract-First: Klare, versionierte APIs (idealerweise coarse-grained), keine Chatty Patterns. Kompatibilitätsfenster definieren.
  • Datenabkopplung: Database-per-service für den extrahierten Teil. Datenfluss über Events (Outbox-Pattern) oder wohldefinierte Sync-Prozesse; Idempotenz sicherstellen.
  • Inkrementelle Teilauslagerung: Zuerst nicht-kritische Pfade, Telemetrie und Rollback-Pfade stehen lassen, bevor Kerntransaktionen verteilt werden.

8) Anti-Patterns und realistische Alternativen

Zu vermeiden:

  • Microservice pro Feature: Führt zu N Services für N Features, aber mit hoher Kopplung über geteilte Schemas und synchrone Kaskaden – ein verteilter Monolith mit schlechterem Latenzprofil.
  • Shared Database über Services: Unterminiert Service-Grenzen, macht Migrationsplanung zur Hölle.
  • Interne Remote Calls für triviale Domäneninteraktionen: Wenn 95% der Interaktion innerhalb eines Teams liegt, ist das Netzwerk nur Ballast.
  • Service Mesh in air-gapped Umgebungen: Komplexität und Operabilität kollidieren mit statischen Netzen und schmalen Betriebs-Teams. mTLS und feste Endpunkte sind oft die praktikablere Wahl.

Realistische Alternativen:

  • Grobgranulare Service-Aufteilung: 2–5 Services mit starken Boundaries (z. B. “Operations Core”, “Public API”, “ML Inference Farm”, “Reporting”), statt 20+ Microlithen.
  • File- oder Message-basierte Übergaben für schwere Artefakte: Für große Bild-/Sensordaten sind robuste File-Drops oder objektbasierte Stores mit sidecar-freier Auth oft betriebssicherer als Chatty RPC.
  • IPC statt Netzwerk, wo Isolation nötig ist: Subprozesse mit klaren Protokollen (z. B. Cap’n Proto, FlatBuffers über Shared Memory) liefern Stabilität ohne Netzwerklast.

9) API- und Datenvertragsdisziplin auch im Monolith

Nur weil intern alles in einem Prozess läuft, heißt das nicht, dass Schnittstellendisziplin egal ist:

  • Versionierte interne Interfaces: Jedes Modul veröffentlicht Ports mit klaren Semantiken, semantischer Versionierung und Deprecation-Plänen.
  • Migrationstechniken: Database-Migrationen vorwärts- und rückwärtskompatibel (expand-contract). Feature Flags für neue Felder/Verhalten.
  • Antikorruptionsschichten: Für Legacy-Teile, die noch nicht refaktoriert sind, klare Adapter, die die Unerfreulichkeiten kaschieren.

10) Sicherheit und Lieferkette

  • Sprache und Isolation: Realtime-Pfade in C++ sind legitim, aber memory safety erfordert Disziplin (Sanitizer in CI, fuzzing). Für untrusted Plugins oder komplexe Parser lohnt Rust oder Prozessisolation.
  • Signierte Artefakte, reproduzierbare Builds: Ein Artefakt, eine Signaturkette, SBOM. In zukunftsfesten Organisationen ist das gelebte Praxis, nicht Poster an der Wand.
  • Secrets und Zertifikate: Eigene PKI, kurzlebige Zertifikate, Rotation über das gleiche Installationssystem. Kein externer Geheimnisspeicher im Internet, wenn air-gapped.
  • Least privilege: Auch im Monolithen sind Subprozesse mit weniger Rechten wertvoll (z. B. Inferenz-Worker ohne Schreibrechte auf zentrale DB).

11) Cloud-native vs. On-Premise: Muster für regulierte Branchen