Jeder will Microservices. Wenige wissen, wie man von einem bestehenden Monolithen dorthin gelangt, ohne die Produktion lahmzulegen. Wir teilen Erfahrungen aus der Zerlegung dreier Enterprise-Monolithen — was funktioniert hat, was nicht, und warum das Strangler Fig Pattern Ihr bester Freund ist.
Wann man Microservices (nicht) einsetzen sollte¶
Martin Fowler sagt es klar: „Don’t start with microservices.” Wenn Sie keine Probleme mit Skalierung, Deployment-Frequenz oder Team-Autonomie haben, fügen Microservices Komplexität ohne Nutzen hinzu.
Microservices machen Sinn, wenn:
- Sie mehr als 3 Entwicklungsteams haben, die an einem Monolithen arbeiten
- Das Deployment eines Features den Release der gesamten Anwendung blockiert
- Verschiedene Teile des Systems unterschiedliche Skalierung benötigen (Checkout vs. Produktkatalog)
- Sie verschiedene Technologien für verschiedene Domänen nutzen wollen (Python für ML, Go für API)
Strangler Fig Pattern¶
Benannt nach dem Würgefeigenbaum, der um einen Baum wächst und ihn allmählich ersetzt. Prinzip: Neue Features bauen Sie als Microservices, alte migrieren Sie schrittweise. Der Monolith und die Microservices laufen parallel.
# DSGVO und IT-Systeme — Technische Vorbereitung auf die Verordnung
/api/users → monolith
/api/orders → monolith
/api/products → monolith
/api/payments → monolith
# Phase 2: Neuer Payment Service, Rest auf dem Monolithen
/api/users → monolith
/api/orders → monolith
/api/products → monolith
/api/payments → payment-service (neuer Microservice)
# Phase 3: Schrittweise Migration
/api/users → user-service
/api/orders → order-service
/api/products → monolith (vorerst)
/api/payments → payment-service
Entscheidend: Niemals ein Big-Bang-Rewrite durchführen. Jede Migration ist ein kleiner, reversibler Schritt. Wenn der neue Service nicht funktioniert, schalten Sie das Routing zurück zum Monolithen.
Domain-Driven Design — Wo schneiden¶
Der häufigste Fehler: Microservices nach technischen Schichten schneiden (UI Service, Business Logic Service, Data Service). Der richtige Ansatz ist nach Business-Domänen zu schneiden (Bounded Contexts).
- Order Context — Bestellerstellung, Bestellstatus, Historie
- Payment Context — Payment Gateway, Erstattungen, Rechnungsstellung
- Inventory Context — Lagerbestände, Reservierungen, Nachbestellungen
- User Context — Registrierung, Authentifizierung, Profil, Einstellungen
Jeder Bounded Context hat seine eigene Datenbank. Kein Teilen von Tabellen zwischen Services. Dies ist die wichtigste Regel und die am schwersten einzuhaltende.
API Gateway¶
Clients sollten nicht direkt mit Dutzenden von Microservices kommunizieren. API Gateway ist ein einzelner Einstiegspunkt:
- Kong — Open Source, Lua Plugins, hohe Performance (nginx-basiert)
- Netflix Zuul — Java, integriert mit dem Spring Cloud Ökosystem
- AWS API Gateway — Managed, integriert mit Lambda
- Traefik — native Docker/Kubernetes Integration, automatische Service Discovery
API Gateway bietet: Routing, Rate Limiting, Authentifizierung, Request/Response Transformation, Aggregation (BFF — Backend for Frontend Pattern).
Verteilte Transaktionen — Saga Pattern¶
In einem Monolithen haben Sie ACID-Transaktionen. In Microservices nicht — jeder Service hat seine eigene Datenbank. Das Saga Pattern löst verteilte Transaktionen als Sequenz lokaler Transaktionen mit kompensierenden Aktionen:
Saga: Bestellerstellung
1. Order Service → Bestellung erstellen (PENDING)
2. Payment Service → Zahlung autorisieren
3. Inventory Service → Waren reservieren
4. Order Service → Bestellung bestätigen (CONFIRMED)
Kompensation (wenn Schritt 3 fehlschlägt):
3c. Inventory Service → (übersprungen — fehlgeschlagen)
2c. Payment Service → Zahlungsautorisierung stornieren
1c. Order Service → Bestellung stornieren (CANCELLED)
Implementierung: Choreografie (Events über Message Broker — einfacher, dezentralisiert) oder Orchestrierung (zentraler Saga-Orchestrator — komplexer, bessere Sichtbarkeit).
Kommunikation zwischen Services¶
Zwei grundlegende Ansätze:
- Synchron (REST/gRPC) — einfacher, erzeugt aber temporale Kopplung. Wenn der Downstream-Service nicht verfügbar ist, schlägt der Aufrufer fehl.
- Asynchron (Events) — Kafka, RabbitMQ. Services sind entkoppelt, aber Eventual Consistency ist schwerer zu debuggen.
Regel: Commands synchron, Events asynchron. „Bestellung erstellen” ist ein REST Call. „Bestellung wurde erstellt” ist ein Event auf einem Kafka Topic.
Observability — Sie müssen sehen, was passiert¶
Ein verteiltes System ohne Observability ist ein Albtraum. Drei Säulen:
- Logging — zentralisierte Logs mit Correlation ID (ELK Stack, Fluentd)
- Metrics — Prometheus + Grafana, RED Metriken (Rate, Errors, Duration)
- Tracing — Jaeger, Zipkin zur Visualisierung des Request-Flusses über Services hinweg
Ohne Distributed Tracing verbringen Sie Stunden damit herauszufinden, welcher der 15 Services den Timeout verursacht hat. Mit Jaeger sehen Sie es in 10 Sekunden.
Datenbank-Zerlegung¶
Der schwierigste Teil der Migration. Ein Monolith hat typischerweise eine große Datenbank mit Foreign Keys zwischen Tabellen. Vorgehen:
- Schritt 1: Tabellen logisch trennen (Schema pro Bounded Context)
- Schritt 2: JOINs zwischen Kontexten durch API-Aufrufe ersetzen
- Schritt 3: Datenbanken physisch trennen
- Schritt 4: Event-Driven-Synchronisierung implementieren, wo Services Daten aus einem anderen Kontext benötigen
Microservices sind ein Marathon, kein Sprint¶
Die Zerlegung eines Monolithen ist ein Prozess, der Monate bis Jahre dauert. Das Strangler Fig Pattern stellt sicher, dass die Produktion die ganze Zeit läuft. Beginnen Sie mit einem Service — idealerweise dem mit der klarsten Domain-Grenze und dem größten Deployment-Schmerz. Lernen Sie darauf den Betrieb von Microservices (Monitoring, Deployment, Debugging) und fahren Sie dann mit weiteren fort.
Brauchen Sie Hilfe bei der Implementierung?
Unsere Experten helfen Ihnen bei Design, Implementierung und Betrieb. Von der Architektur bis zur Produktion.
Kontaktieren Sie uns