Warum Service-Grenzen aus der Fachdomäne kommen, warum die Datenbank der schwierige Teil ist und in welcher Reihenfolge extrahiert wird.
Transparenzhinweis. legacy-modernisierung.de wird von der Chudovo OÜ betrieben. Die Zeitangaben in diesem Leitfaden sind die Spannen, die Chudovo aus eigenen abgeschlossenen Projekten veröffentlicht — Referenzwerte eines Anbieters, keine Branchendurchschnitte. Die zitierten Muster stammen von Martin Fowler, AWS und Chris Richardson.
Zuerst: sollten Sie überhaupt?
Microservices sind kein Reifegrad, den eine Architektur erreicht. Sie sind ein Tausch: Sie geben die Einfachheit eines einzelnen Deployments auf und erhalten dafür unabhängige Skalierung und unabhängige Releases. Wer den Tausch macht, ohne die rechte Seite zu brauchen, zahlt nur den Preis.
Der Preis ist konkret. Jeder Service braucht eine eigene Deployment-Pipeline, eigenes Monitoring und eigene Datenhaltung. Netzwerkaufrufe ersetzen Methodenaufrufe und bringen Latenz, Teilausfälle und Retry-Logik mit. Fehlersuche spannt sich über Prozessgrenzen hinweg.
Vier Fälle, in denen der Tausch sich nicht lohnt:
- Kleine oder wenig dynamische Anwendungen. Der Betriebsaufwand übersteigt den Nutzen
- Produkte in früher Entwicklungsphase. Das Domänenmodell ändert sich ständig, Service-Grenzen lassen sich noch nicht sinnvoll setzen — und falsch gesetzte Grenzen sind teuer zu korrigieren
- Kleine Teams mit vielen Services. Mehr Zeit geht in Infrastruktur und Abstimmung als in Entwicklung
- Gleichmäßige, vorhersehbare Auslastung. Was ein Monolith problemlos abdeckt, braucht keine unabhängige Skalierung
Ein Monolith mit sauberen internen Modulgrenzen ist kein Problem, das gelöst werden muss. Ein Monolith, dessen Module ineinander übergehen, wird durch die Aufteilung in verteilte Services nicht besser — er wird zu einem verteilten System mit denselben unklaren Grenzen, nur mit Netzwerk dazwischen.
Anzeichen, dass der Monolith tatsächlich die Einschränkung ist
Monolithische Architektur scheitert selten plötzlich. In der Regel entstehen zuerst erkennbare betriebliche und organisatorische Probleme:
Langsame und risikoreiche Deployments. Jede Änderung erfordert einen vollständigen Build, Tests und ein Deployment des gesamten Systems. Eine kleine Korrektur im Abrechnungsmodul durchläuft denselben Release-Prozess wie eine große Funktionserweiterung. Teams reduzieren die Release-Frequenz, um Risiken zu vermeiden — und werden dadurch langsamer.
Teile der Codebasis lassen sich kaum noch sicher ändern. Zentrale Module bauen über die Zeit viele Abhängigkeiten auf. Entwickler vermeiden Änderungen, weil die Auswirkungen schwer vorhersehbar sind.
Ineffiziente Skalierung. Die gesamte Anwendung muss skaliert werden, um die Anforderungen einer einzelnen stark genutzten Komponente zu erfüllen. Braucht die Suche deutlich mehr Ressourcen, wird trotzdem das komplette System entsprechend dimensioniert.
Ein einzelner Fehler beeinträchtigt die gesamte Anwendung. Es besteht keine ausreichende Trennung zwischen den Komponenten auf Prozessebene.
Mehrere Teams werden durch gemeinsame Codeverantwortung ausgebremst. Merge-Konflikte, zusätzlicher Abstimmungsaufwand, gemeinsame Release-Zyklen. Teams können nicht unabhängig deployen.
Die ersten beiden Punkte beschreiben technische Schulden und sind oft durch Refactoring innerhalb des Monolithen zu beheben. Erst die letzten drei sind Argumente für eine Aufteilung: Sie betreffen Eigenschaften, die ein einzelnes Deployment strukturell nicht liefern kann.
Woher Service-Grenzen kommen
Das ist die Entscheidung, die über Erfolg oder Scheitern bestimmt, und sie wird am häufigsten falsch getroffen.
Grenzen kommen aus der Fachdomäne, nicht aus technischen Schichten. Ein „Datenbank-Service“, ein „Validierungs-Service“ und ein „Benachrichtigungs-Service“ sind keine Microservices, sondern eine über das Netzwerk verteilte Schichtenarchitektur — mit allen Kosten des verteilten Systems und keinem seiner Vorteile.
Eine brauchbare Grenze hat drei Eigenschaften:
- Sie kapselt eine vollständige Geschäftsfähigkeit. „Bestellungen“ umfasst Annahme, Validierung, Statusverwaltung und die zugehörigen Daten — nicht nur eine Tabelle
- Sie besitzt ihre Daten. Kein anderer Service liest oder schreibt direkt in diese Tabellen
- Sie ändert sich aus eigenen Gründen. Ändert sich der Service immer dann, wenn sich ein anderer ändert, gehören beide zusammen
Die praktische Methode: Analysieren Sie die abgegrenzten Kontexte des bestehenden Monolithen, bevor Sie extrahieren — Kopplungen, Datenverantwortlichkeiten, Integrationsabhängigkeiten. Die Reihenfolge der Extraktion ergibt sich aus diesem Audit, nicht aus Vermutungen. Falsch gesetzte Grenzen sind nach dem Deployment deutlich schwieriger zu korrigieren als vorher auf dem Papier.
Das Strangler-Fig-Muster
Der Begriff stammt von Martin Fowler und beschreibt das Strangler-Fig-Muster: Statt das Altsystem zu ersetzen, wächst das neue System um es herum, bis das alte nichts mehr tut und abgeschaltet werden kann. AWS führt dasselbe Muster in seiner Prescriptive Guidance für die Zerlegung von Monolithen.
Die Fassade ist der eigentliche Mechanismus. Ohne sie gibt es keinen Weg, einen Service schrittweise in Betrieb zu nehmen, und jede Umstellung wird zu einem Stichtag, an dem etwas schiefgehen kann.
Konkret:
- Fassade einziehen, ohne etwas zu ändern. Der gesamte Traffic geht weiter an den Monolithen. Dieser Schritt ändert kein Verhalten und muss es auch nicht — er schafft den Kontrollpunkt
- Eine Funktion extrahieren. Der neue Service läuft parallel und erhält einen kleinen Traffic-Anteil
- Anteil erhöhen, wenn der Service trägt. 10 % → 50 % → 100 %, mit Rückweg bei jedem Schritt
- Alten Pfad entfernen. Erst wenn der neue Pfad über eine Weile unter Produktionslast stabil war
- Wiederholen, bis der Monolith nichts Wesentliches mehr tut
Schritt 4 wird am häufigsten übersprungen. Bleibt der alte Pfad als Sicherheitsnetz bestehen, hat die Organisation beide Systeme zu pflegen und keines abgeschaltet — das ist der Zustand, in dem Migrationen jahrelang stecken bleiben.
Die Datenbank ist der schwierige Teil
Services zu extrahieren ist Arbeit. Daten zu entflechten ist das Projekt.
Im Monolithen ist die gemeinsame Datenbank die eigentliche Integrationsschicht. Fremdschlüssel über Domänengrenzen hinweg erzwingen Regeln, die nirgends dokumentiert sind. Eine einzelne Transaktion schreibt über mehrere Fachbereiche hinweg und erhält Konsistenz kostenlos.
Stufe 2 ist der gefährliche Zustand. Zwei Datenbestände müssen übereinstimmen, während beide geschrieben werden. Wer in zwei Datenbanken gleichzeitig schreibt, hat keine Transaktion mehr: Fällt der zweite Schreibvorgang aus, divergieren die Daten still. Deshalb wird die Synchronisierung über Events geführt und nicht über doppelte Schreibzugriffe — und deshalb braucht Stufe 2 ein Enddatum.
Reihenfolge, die funktioniert:
- Lesezugriffe trennen, bevor Schreibzugriffe getrennt werden. Der neue Service liest aus eigener Quelle, schreibt aber noch in die alte
- Die Datenhoheit verschieben. Ein Service wird alleiniger Schreiber seiner Tabellen
- Direkte Zugriffe anderer Services entfernen. Was andere brauchen, kommt über API oder Event
- Physisch trennen. Erst jetzt wird die Datenbank aufgeteilt
Wer mit Schritt 4 beginnt, baut sich Stufe 2 als Dauerzustand.
Verteilte Transaktionen: was den Rollback ersetzt
Sobald ein Geschäftsvorgang mehrere Services berührt, gibt es kein ROLLBACK mehr. An seine Stelle tritt das Saga-Muster: Der Vorgang wird in eine Folge lokaler Transaktionen zerlegt, und jeder Schritt hat eine kompensierende Aktion, die ihn fachlich rückgängig macht.
Der Unterschied ist nicht technisch, sondern fachlich. Eine Zahlung wird nicht „zurückgerollt“, sondern erstattet. Eine reservierte Ware wird nicht „entreserviert“, sondern freigegeben — und möglicherweise hat sie in der Zwischenzeit jemand anders bekommen. Diese Zwischenzustände sind in einem Monolithen unsichtbar und werden in einem verteilten System zu Fällen, die das Fachkonzept beantworten muss.
Das ist der Punkt, an dem Microservices Entscheidungen erzwingen, die vorher niemand treffen musste. Wer sie nicht trifft, bekommt sie als Produktionsvorfälle zurück.
Welchen Service zuerst extrahieren
Nicht den wichtigsten und nicht den schwierigsten. Der erste Service hat eine andere Aufgabe: Er soll beweisen, dass der Weg funktioniert — Deployment-Pipeline, Monitoring, Fassade, Datentrennung.
Gute Kandidaten:
- Klare Grenze, wenig Kopplung an den Rest
- Eigene Daten, die kaum jemand anders liest
- Echter Nutzen bei Ablösung, damit der Schritt sich lohnt
- Überschaubares Risiko bei Ausfall
Typisch passen Benachrichtigungen, Reporting, Suche oder Dateiverwaltung. Abrechnung und Authentifizierung passen selten — zu viel hängt daran.
Dauer
Veröffentlichte Spannen von Chudovo für die Migration von Monolithen zu Microservices:
| Umfang | Dauer |
|---|---|
| Extraktion von zwei bis drei Services aus einem mittelgroßen Monolithen | 3–6 Monate |
| Vollständige Zerlegung eines großen Enterprise-Monolithen | 12–24 Monate |
Die Migration erfolgt schrittweise; jede Phase liefert produktionsreife Services statt unfertiger Zwischenergebnisse. Die Spanne bei der vollständigen Zerlegung hängt vor allem an der Anzahl der Services — und daran, wie verflochten die Datenbank ist.
Wo diese Migrationen scheitern
Grenzen nach technischen Schichten statt nach Fachdomänen. Das häufigste und teuerste Muster, weil die Korrektur nach dem Deployment ungleich aufwendiger ist.
Die gemeinsame Datenbank bleibt. Services sind getrennt, greifen aber weiter auf dieselben Tabellen zu. Dann existiert die Kopplung unverändert — nur unsichtbar.
Keine Fassade. Ohne Kontrollpunkt wird jede Umstellung zum Stichtag ohne Rückweg.
Der alte Pfad wird nie entfernt. Beide Systeme laufen weiter, die Kosten addieren sich, der Nutzen bleibt aus.
Stufe 2 wird zum Dauerzustand. Die Event-Synchronisierung zwischen altem und neuem Schema sollte Wochen dauern, nicht Quartale.
Betrieb kommt zuletzt. Verteiltes Tracing, zentrale Logs und Service-Monitoring werden gebraucht, sobald der zweite Service live geht — nicht wenn der zehnte live geht.
Zu viele Services zu früh. Ein Monolith, der in dreißig Services zerlegt wird, bevor der erste in Produktion trägt, liefert dreißig unbewiesene Annahmen.
Woran sich messen lässt, ob es gewirkt hat
Vor Beginn erheben, danach messen:
- Deployment-Frequenz je Service — der eigentliche Zweck der Aufteilung
- Vorlaufzeit von Merge bis Produktion
- Fehlerquote bei Änderungen, getrennt für Services und Monolith
- Wiederherstellungszeit nach einem Vorfall
- Anteil der Vorfälle, die nur einen Service betreffen — misst, ob die Fehlerisolierung tatsächlich greift
- Zahl der Services, die eigenständig deploybar sind — nicht die Zahl der Services
Der letzte Punkt ist der ehrlichste. Ein Service, der nur gemeinsam mit zwei anderen deployt werden kann, ist kein Service, sondern ein verteiltes Modul.
FAQ
Wie unterscheidet sich eine Microservices-Architektur von einem Monolithen? Ein Monolith ist eine Anwendung, bei der sämtliche Funktionalität in einer einzigen deploybaren Einheit gebündelt ist. In einer Microservices-Architektur wird die Anwendung in unabhängig deploybare Services unterteilt, wobei jeder Service einer spezifischen Domäne zugeordnet ist. Dadurch entsteht ein Kompromiss: Die Anwendung trägt nun die Komplexität eines verteilten Systems.
Ist die Migration zu Microservices für alle Anwendungen geeignet? Nein. Microservices bringen betrieblichen Mehraufwand mit sich, da jeder Service eine eigene Deployment-Pipeline, Monitoring und Datenhaltung benötigt. Bei kleinen oder wenig dynamischen Anwendungen ist dies nicht sinnvoll. Produkte in früher Entwicklungsphase ändern ihr Domänenmodell ständig, sodass Service-Grenzen nicht sinnvoll definiert werden können — und falsch gesetzte Grenzen sind teuer zu ändern. Bei kleinen Teams mit vielen Services geht mehr Zeit für Infrastruktur und Kommunikation verloren als für die Entwicklung.
Wie lange dauert die Migration? Die Extraktion von zwei bis drei Services aus einem mittelgroßen Monolithen kann drei bis sechs Monate dauern. Die vollständige Zerlegung eines großen Enterprise-Monolithen kann zwölf bis vierundzwanzig Monate in Anspruch nehmen, je nach Anzahl der Services.
Muss jeder Service eine eigene Datenbank haben? Ja, sonst besteht die Kopplung fort. Services, die sich Tabellen teilen, können nicht unabhängig deployt werden, weil jede Schemaänderung alle betrifft. Eine geteilte Datenbank ist in Stufe 2 ein Übergangszustand, kein Zielbild.
Was passiert mit Transaktionen über Servicegrenzen hinweg? Sie werden durch Sagas ersetzt: eine Folge lokaler Transaktionen mit kompensierenden Aktionen. Fachlich bedeutet das, Zwischenzustände zu definieren, die es im Monolithen nicht gab.
Kann der Monolith während der Migration in Betrieb bleiben? Ja — das ist der Sinn des Strangler-Fig-Musters. Der Monolith bleibt aktiv, bis alle Services bereitgestellt sind und stabil funktionieren.
Was, wenn die Service-Grenzen sich als falsch erweisen? Zusammenlegen ist einfacher als weiter aufteilen. Zwei Services, die sich immer gemeinsam ändern, gehören zusammen — das rückgängig zu machen ist legitim und kein Scheitern.