Monolith vs. Microservices: Wann der Monolith gewinnt – Architekturentscheidungen aus industrieller Praxis
Wer industrielle Softwaresysteme baut, kämpft selten mit Amazon-Scale, dafür aber mit Rahmenbedingungen, die in vielen “Cloud-first”-Architekturartikeln kaum vorkommen: air-gapped Netzwerke, Vor-Ort-Betrieb mit begrenztem IT-Personal, harte Audit-Anforderungen, deterministische Latenzbudgets bis in den Millisekundenbereich, heterogene Hardware von x86 bis ARM und GPU-Karten, und Release-Prozesse, die man auch noch in fünf Jahren reproduzierbar erklären können muss. In genau diesem Umfeld wird die “Microservices um jeden Preis”-Maxime schnell zur operativen Last. Und der gute, alte Monolith – sauber modularisiert – gewinnt überraschend oft.
Dieser Beitrag legt die Architekturdimensionen offen, aus denen sich diese Entscheidung ableiten lässt, und zeigt konkrete Muster, wie ein modularer Monolith in regulierten On-Prem-Setups Skalierbarkeit, Änderbarkeit und Betriebssicherheit erzielt, ohne in einen “Distributed Monolith” abzurutschen. Die Beispiele stammen aus realen Plattformen für Vermessung, Flottenintelligenz, visuelle Inspektion und Trainingssysteme.
1) Ausgangslage in regulierten/industriellen Systemen
Typische Randbedingungen:
- On-Premise, teils air-gapped oder streng segmentierte Netze (OT/IT-Trennung, kein ausgehender Traffic).
- Small-to-medium Teams, klare Verantwortungsketten, begrenzte SRE-Kapazitäten.
- Langlebige Systeme (7–15 Jahre), Lifecycle-Management wichtiger als kurzfristige Feature-Geschwindigkeit.
- Hohe Anforderungen an Nachvollziehbarkeit: deterministische Builds, signierte Artefakte, Audits, Reproduzierbarkeit.
- Datenhoheit: Keine Abhängigkeit von US-Clouds, DSGVO-konforme Verarbeitung, teils nationale Regularien.
- Heterogene Latenz- und Durchsatzanforderungen: Von 30 ms für Bildverarbeitung am Band bis Batch-Analytik nachts.
- Edge-Topologien: Rechenknoten in Werken, Zügen, Fahrzeugen mit sporadischer Synchronisation zur Zentrale.
In diesem Kontext entscheiden Architekturformen nicht nur über Codeorganisation, sondern über Betriebskosten, Auslieferbarkeit, Sicherheit und rechtliche Angreifbarkeit.
2) Entscheidungsdimensionen und harte Trade-offs
Die Monolith-vs-Microservices-Entscheidung ist eine Funktion folgender Achsen:
- Team-Topologie und Verantwortlichkeit: Ein Team, das zehn Services owns, braucht Produktionsreife in Observability, CI/CD, Incident Response, Paketierung – multipliziert mit der Serviceanzahl. Ist diese Kapazität realistisch verfügbar?
- Deploy-Topologie: Air-gapped oder mit Proxy? Statische IPs, keine dynamische Service Discovery? Je fragiler das Netzwerk, desto teurer werden verteilte Grenzen.
- Konsistenz vs. Entkopplung: Brauchen Sie ACID-Transaktionen über mehrere Domänenvorgänge hinweg? Oder reicht eventual consistency mit Sagas/Outbox?
- Latenzbudgets: In-Prozess-Aufrufe liegen bei Mikrosekunden bis wenige Millisekunden, Remote Calls brauchen Größenordnungen mehr – plus Retries und Circuit Breaking.
- Änderlichkeit des Domänenmodells: Solange Domänenschnitte schwammig sind, ist das Zerschneiden in Services vorzeitig. Ein modulärer Monolith hält Domänengrenzen intern verhandelbar.
- Betriebsreife: Logging, Metriken, Tracing, Feature Flags, Blue/Green, Canary – in On-Prem-Umgebungen oft nur eingeschränkt möglich. Jeder zusätzliche Prozess ist ein operativer Kostenfaktor.
- Sicherheits- und Lieferkette: Signed builds, SBOM, reproduzierbare Artefakte, Rollbacks. Ein Artefakt ist einfacher zu auditieren als 15, die in 5 Versionen kombiniert laufen.
3) Der modulare Monolith als Architekturpattern
Ein Monolith ist nicht “ein großer Haufen Code”. Ein moderner modularer Monolith kombiniert:
- Bounded Contexts (DDD) als explizite Module mit klaren Ownership-Grenzen.
- Ports-and-Adapters (Hexagonale Architektur): Interne Domänenlogik isoliert, Adapter für UI, Persistenz, Messaging, Hardware.
- Interner Event-Bus (in-prozess) für lose Kopplung ohne Netzwerk. Asynchronität ohne Serialisierungs- und Netzwerk-Overhead.
- Modulgrenzen technisch abgesichert: Getrennte Namespaces, keine zyklischen Abhängigkeiten, interne Schnittstellen versioniert.
- Plugin-Systeme für erweiterbare Fähigkeiten (z. B. neue ML-Modelle, neue Sensorprotokolle) mit wohldefinierten Contracts.
- Selektive Prozess-Isolation: Wenn nötig, einzelne Komponenten als separate Prozesse mit klaren IPC-Schnittstellen (z. B. für untrusted Code, GPU-intensive Worker), aber weiterhin im selben Deploy-Artefakt orchestriert.
Dieses Muster erlaubt, das System als ein deploybares Artefakt zu liefern, aber intern genügend Reibung zu erzeugen, damit keine Wildwüchse entstehen. Es verhindert die “verteilte Monolith”-Falle, in der jede Domänenänderung zehn Services synchron erfordert.
4) Konkrete Architekturskizzen aus Projekten
Beispiel A: Visuelle Inspektion in der Fertigung
- Problem: 6–12 Kamerastreams, Latenzbudget < 80 ms von Frame-Ingest bis Befund; UI am Edge; Modellupdates signiert; Offline-Betrieb obligatorisch.
- Architektur:
- Monolithischer Core in C++ für Realtime-Pfade (Frame-Ingest, Preprocessing, Inferenz-Treiber), mit GPU-Anbindung.
- Plugin-Adapter für Modelle (z. B. ONNX, TensorRT) als dynamisch ladbare Module; Versionierung und Capability-Checks.
- Python-gestützte Training- und Evaluation-Toolchain separat, aber Artefaktauslieferung an das Edge-System via signierter Pakete. Keine Python-Laufzeit im Produktionspfad.
- Interner Event-Bus: “FrameCaptured”, “InferenceCompleted”, “AnomalyDetected”. UI-Adapter (Qt) abonniert nur relevante Events.
- Persistenz via PostgreSQL für Metadaten und Befunde; Rohbilder als rotiertes Fileset auf NVMe. Asynchrone Replikation ausgewählter Metadaten zur Zentrale.
- Selektive Prozess-Isolation für Modellinferenz, um GPU-Abstürze zu kapseln (separater Worker-Prozess mit Zero-Copy-Sharing, Ringbuffer, Shared Memory).
- Warum Monolith? Netzwerkinstabile Zellen, harte Latenz und ACID-Anforderungen für Befund + Parameterstände. Betrieblich ein Installationspaket, reproduzierbar, offline updatebar.
Beispiel B: Flottenintelligenz im Bahnkontext
- Problem: Edge-Nodes im Zug, wechselnde Konnektivität, lokale Analytik (Anomalieerkennung), Sync-Fenster im Depot, zentrale Auswertung.
- Architektur:
- Edge: Modularer Monolith mit Ports/Adapters, persistiert Rohdaten lokal, komprimiert/aggregiert für Upload. Interprozess-Worker für CPU/GPU-gebundene Jobs. Aufgabenplaner, der Fenster für Upload nutzt.
- Zentrale: Monolithische Kernplattform mit klaren Bounded Contexts (Asset-Registry, Health-Events, Maintenance-Planning). Separate, grobgranulare Services nur für klar abtrennbare Workloads (z. B. Public Reporting API).
- Warum Monolith? Edge benötigt robuste, einfache Betriebsführung. Zentrale benötigt starke Konsistenz in der Instandhaltungsplanung. Eine Handvoll gezielter Services ersetzt nicht die Kernlogik – sie exponiert nur stabile, externe Integrationspunkte.