Microservices oder Monolith: wann sich die Zerlegung wirklich lohnt
Microservices oder Monolith: wann sich die Zerlegung wirklich lohnt
Artikel-Übersicht
Die Frage „Microservices oder Monolith" wird fast immer technisch gestellt und ist fast immer eine organisatorische. Dieser Artikel dreht sie deshalb um: Er beginnt mit sauberen Definitionen — was Microservices ausmacht und was ein Monolith wirklich ist, nämlich eine Deployment-Einheit und keine Altlast. Danach kommt der Abschnitt, der im deutschsprachigen Raum kaum besetzt ist: der modulare Monolith, der Modulgrenzen ohne Verteilung liefert und sich später zerlegen lässt. Es folgen eine Vergleichstabelle über acht Kriterien, die Abgrenzung zu SOA, fünf Entscheidungsfragen mit klarer Auswertung und eine ehrliche Aufstellung dessen, was die Zerlegung kostet. Zum Schluss der Weg, wie man später doch zerlegt — entlang der Modulgrenzen, die man vorher gezogen hat.
Was Microservices sind
Microservices sind eigenständig deploybare Dienste, die je einen fachlichen Ausschnitt besitzen — samt eigener Datenhaltung.
An drei Merkmalen hängt die Definition, und wenn eines fehlt, hat man etwas anderes:
- Eigenständiges Deployment. Ein Dienst lässt sich ausrollen, ohne dass ein anderer mit ausgerollt werden muss. Das ist die eigentliche Zusage.
- Eigene Daten. Kein gemeinsames Datenbankschema. Wenn zwei Dienste auf dieselbe Tabelle schreiben, sind sie nicht unabhängig, sondern verteilt gekoppelt — die schlechteste aller Welten.
- Kommunikation nur über Schnittstellen. Keine geteilten Bibliotheken mit Geschäftslogik, kein direkter Datenbankzugriff über die Grenze hinweg.
Was in der Definition nicht vorkommt: eine Größenangabe. „Micro" ist irreführend. Die Größe eines Dienstes bemisst sich nicht in Codezeilen, sondern daran, ob er einem Team gehört und ob er allein deploybar ist.
Was ein Monolith ist — und was er nicht ist
Ein Monolith ist eine Anwendung, die als eine Einheit ausgeliefert wird. Mehr sagt der Begriff nicht.
Diese Klarstellung ist nötig, weil „Monolith" als Schimpfwort benutzt wird. Gemeint ist dann meist etwas anderes: ein System ohne innere Struktur, in dem alles alles kennt. Das ist aber kein Merkmal der Deployment-Form, sondern eine Frage der Modulgrenzen.
Ein gut geschnittener Monolith ist keine Altlast. Er hat klare Module, definierte Schnittstellen zwischen ihnen und eine Struktur, die man erklären kann. Er wird nur eben als Ganzes ausgerollt.
Der Unterschied ist wichtig, weil er die Frage entkoppelt: Struktur und Deployment sind zwei Entscheidungen, nicht eine. Man kann sauber strukturieren, ohne zu verteilen. Umgekehrt geht es nicht — wer verteilt, ohne vorher zu strukturieren, verteilt sein Durcheinander.
Der modulare Monolith
Zwischen den beiden Extremen liegt die Variante, die für die meisten Teams die richtige ist und im deutschsprachigen Netz kaum beschrieben wird.
Ein modularer Monolith ist ein System mit erzwungenen Modulgrenzen in einer einzigen Deployment-Einheit. Die Module kennen einander nur über definierte Schnittstellen, haben getrennte Datenbereiche und gehören jeweils einem fachlichen Zusammenhang. Was fehlt, ist ausschließlich die Verteilung über Prozessgrenzen.
Der entscheidende Punkt sind die erzwungenen Grenzen. Eine Modulstruktur, die nur aus Ordnern besteht, hält keine zwei Jahre. Was hilft:
- Modulsysteme der Sprache, die Sichtbarkeit über Paketgrenzen hinweg tatsächlich beschränken.
- Architekturtests, die verbotene Abhängigkeiten im Testlauf rot färben. Zehn Zeilen genügen dafür; wie das aussieht, steht in Clean Architecture: Schichten, Grenzen und die Frage, was man weglässt.
- Getrennte Schemata in derselben Datenbank, mit der Regel, dass kein Modul direkt in das Schema eines anderen schreibt.
Und der Satz, um den es geht: Ein modularer Monolith lässt sich später zerlegen. Ein verteiltes Chaos lässt sich nicht wieder zusammensetzen. Wer die Grenzen zieht, aber die Verteilung aufschiebt, behält beide Optionen. Wer verteilt, bevor er die Grenzen kennt, hat die Korrektur um Größenordnungen verteuert.
Woher die Grenzen kommen sollten, ist eine fachliche Frage — das ist der Gegenstand von Domain-Driven Design.
Der Vergleich
| Kriterium | Monolith | Modularer Monolith | Microservices |
|---|---|---|---|
| Deployment | eine Einheit | eine Einheit | je Dienst einzeln |
| Datenhaltung | gemeinsam | getrennte Schemata, gemeinsame Instanz | je Dienst eigen |
| Teamzuschnitt | ein Team | ein bis wenige Teams | ein Team je Dienst |
| Skalierung | nur als Ganzes | nur als Ganzes | je Dienst einzeln |
| Betriebsaufwand | gering | gering | hoch |
| Testbarkeit | einfach, aber langsam | einfach, Module isoliert testbar | Vertragstests nötig |
| Fehlersuche | ein Prozess, ein Log | ein Prozess, ein Log | verteiltes Tracing nötig |
| Änderungskosten bei falschem Schnitt | Refactoring | Refactoring | Migration |
Die letzte Zeile ist die teuerste. Ein falsch geschnittenes Modul verschiebt man an einem Nachmittag. Einen falsch geschnittenen Dienst zusammenzuführen bedeutet Datenmigration, Schnittstellenumbau und Ausrollplanung.
Und was war noch mal SOA?
Serviceorientierte Architektur hatte dieselbe Grundidee — fachlich geschnittene Dienste mit definierten Schnittstellen — und einen entscheidenden Unterschied: eine zentrale Vermittlungsschicht, den Enterprise Service Bus, der Weiterleitung, Umwandlung und teils Geschäftslogik übernahm.
Genau dieser Bus wurde zum Engpass, technisch wie organisatorisch. Microservices reagieren darauf mit dem Grundsatz „schlaue Endpunkte, dumme Leitungen": Die Logik liegt in den Diensten, dazwischen wird nur transportiert.
Wer heute eine zentrale Integrationsplattform baut, durch die alle Aufrufe laufen und in der Umwandlungen stattfinden, sollte wissen, dass er SOA baut — das kann richtig sein, aber es sollte eine Entscheidung sein.
Die eigene Datenhaltung: der Punkt, an dem es ernst wird
Von den drei Merkmalen aus der Definition ist die eigene Datenhaltung dasjenige, das am häufigsten geopfert wird — und dasjenige, dessen Verlust am teuersten ist.
Der Grund für die Trennung ist nicht Ideologie, sondern Kopplung. Solange zwei Dienste auf dieselbe Tabelle schreiben, kann keiner sein Schema ändern, ohne den anderen zu brechen. Damit ist die zugesagte Unabhängigkeit weg, und übrig bleibt der Betriebsaufwand ohne den Nutzen. Für dieses Muster gibt es den treffenden Namen verteilter Monolith: alle Kosten der Verteilung, keiner ihrer Vorteile.
Was die Trennung praktisch bedeutet:
Auswertungen über mehrere Dienste werden zum eigenen Problem. Ein JOIN über zwei Dienstgrenzen existiert nicht. Wer eine Übersicht braucht, die Daten aus drei Diensten zusammenführt, baut entweder einen aufrufenden Dienst, der die Teile einsammelt, oder er repliziert die benötigten Felder in ein eigenes Lesemodell.
Das Lesemodell ist meist die bessere Antwort. Jeder Dienst veröffentlicht Ereignisse über seine Änderungen, ein Auswertungsdienst hört zu und baut daraus eine für Abfragen optimierte Sicht. Der Preis ist, dass diese Sicht nicht sofort aktuell ist — was fachlich fast immer in Ordnung ist, aber ausdrücklich abgestimmt gehört.
Referenzielle Integrität endet an der Dienstgrenze. Es gibt keinen Fremdschlüssel über zwei Datenbanken. Ein Dienst muss damit umgehen, dass eine referenzierte Entität in einem anderen Dienst nicht mehr existiert.
Wer diese drei Punkte nicht beantworten kann, sollte nicht zerlegen. Sie sind der eigentliche Aufwand, nicht das Aufteilen des Codes.
Beispiele aus der Praxis — und die Gegenrichtung
Über die bekannten Zerlegungsgeschichten der großen Plattformen ist viel geschrieben worden, und sie werden regelmäßig falsch zitiert. Zwei Punkte, die man dabei im Blick behalten sollte:
Erstens: Diese Unternehmen hatten das Problem, für das Microservices gebaut wurden. Hunderte Teams, die unabhängig ausrollen wollten, und Lastspitzen, die nur einzelne Bereiche betrafen. Wer fünfzehn Entwickler hat, hat dieses Problem nicht.
Zweitens: Es gibt die Gegenrichtung, und sie ist besser dokumentiert, als man denkt. In den letzten Jahren haben mehrere Unternehmen öffentlich beschrieben, wie sie Dienste wieder zusammengeführt haben — meist mit derselben Begründung: Die Zerlegung war feiner geschnitten als die Organisation, der Kommunikationsaufwand zwischen den Diensten überstieg den Nutzen, und die Latenz vieler kleiner Aufrufe wurde spürbar.
Die Lehre daraus ist nicht „Microservices sind schlecht", sondern: Die richtige Granularität ist die der Organisation, nicht die der Fachlichkeit. Ein fachlich sauberer Schnitt in zwanzig Kontexte bei vier Teams ergibt zwanzig Dienste, um die sich niemand kümmert.
Die fünf Fragen vor der Entscheidung
- Wie viele Teams arbeiten am System? Unter drei Teams ist die Teamunabhängigkeit kein Argument, weil es keine gibt.
- Deployen die Teile unterschiedlich oft? Wenn alles im selben Rhythmus ausgerollt wird, bringt eigenständiges Deployment nichts.
- Skalieren die Teile unterschiedlich? Wenn ein Bereich hundertmal mehr Last hat als der Rest, ist getrennte Skalierung ein echter Gewinn. Wenn alles gleichmäßig wächst, skaliert man den Monolithen billiger.
- Gibt es Betriebskompetenz für verteilte Systeme? Verteiltes Tracing, Dienstverzeichnis, Konfiguration, Geheimnisverwaltung, Ausrollautomatisierung — das ist eine eigene Disziplin.
- Sind die fachlichen Grenzen bekannt? Wenn nicht, ist jeder Schnitt geraten.
Vier von fünf mal Nein bedeutet: modularer Monolith. Und das ist kein Kompromiss, sondern die Empfehlung.
Was die Zerlegung kostet
Ehrlich und vollständig, weil diese Liste in den meisten Artikeln fehlt:
- Verteilte Transaktionen. Was in einem Prozess eine Datenbanktransaktion war, wird zu einem mehrschrittigen Ablauf mit Kompensation. Es gibt keine atomare Klammer über Dienstgrenzen.
- Netzwerklatenz und -fehler. Jeder Aufruf kann langsam sein, fehlschlagen oder doppelt ankommen. Idempotenz wird zur Pflicht statt zur guten Praxis.
- Beobachtbarkeit über Grenzen. Eine Anfrage, die durch fünf Dienste läuft, ist ohne durchgehende Korrelations-ID nicht nachvollziehbar.
- Versionierung der Schnittstellen. Zwei Dienste werden unabhängig ausgerollt — also müssen sie in zwei Versionen gleichzeitig zusammenarbeiten.
- Testaufwand. Ende-zu-Ende-Tests über viele Dienste sind langsam und brüchig. Der Ersatz sind Vertragstests, und die muss jemand schreiben und pflegen.
- Lokale Entwicklungsumgebung. Fünfzehn Dienste auf einem Notebook zu starten ist ein eigenes Problem mit eigenen Werkzeugen.
Keiner dieser Punkte ist unlösbar. Zusammen ergeben sie einen dauerhaften Aufwand, der sich nur rechnet, wenn er einem Nutzen gegenübersteht — und der Nutzen heißt fast immer Teamunabhängigkeit.
Wie man später doch zerlegt
Der Weg heraus aus dem Monolithen ist nicht der große Umbau, sondern das schrittweise Herauslösen entlang bestehender Modulgrenzen:
- Eine Fassade vor das System stellen, die Aufrufe entgegennimmt und weiterleitet.
- Ein Modul als eigenen Dienst herausziehen — das mit der klarsten Grenze, nicht das größte.
- Die Fassade auf den neuen Dienst umleiten.
- Datenhaltung trennen, was der aufwendigste Schritt ist.
- Alte Implementierung entfernen.
Das Verfahren funktioniert genau dann gut, wenn die Modulgrenzen vorher stimmen. Deshalb ist der modulare Monolith kein Aufschub der Entscheidung, sondern ihre Vorbereitung.
Häufige Fragen
Was versteht man unter Microservices? Eigenständig deploybare Dienste mit je eigenem fachlichen Ausschnitt und eigener Datenhaltung, die nur über Schnittstellen miteinander sprechen.
Was ist ein monolithisches System? Eine Anwendung, die als eine Einheit ausgeliefert wird. Der Begriff sagt nichts über die innere Struktur aus — ein Monolith kann sauber modularisiert sein.
Was ist ein modularer Monolith? Ein System mit erzwungenen Modulgrenzen in einer Deployment-Einheit. Es liefert die Struktur von Microservices ohne deren Betriebsaufwand und lässt sich später zerlegen.
Wann lohnen sich Microservices? Wenn mehrere Teams unabhängig ausrollen wollen, Teile unterschiedlich skalieren müssen und Betriebskompetenz für verteilte Systeme vorhanden ist. Fehlt eines davon, überwiegen die Kosten.
Wie groß sollte ein Microservice sein? Nicht in Zeilen messbar. Das Maß ist: Er passt in einen Kopf, gehört einem Team und lässt sich allein ausrollen.
Was ist der Unterschied zu SOA? Die zentrale Vermittlungsschicht. SOA legt Umwandlung und teils Logik in einen Bus, Microservices halten die Leitung dumm und die Endpunkte schlau.
Zusammenfassung und praktische Tipps
Die Entscheidung für oder gegen Microservices ist eine Organisationsentscheidung mit technischen Folgen — nicht umgekehrt. Die wichtigsten Punkte:
- Microservices lösen ein Teamproblem, kein technisches. Ohne mehrere Teams fehlt der Hauptnutzen.
- Monolith heißt eine Deployment-Einheit, nicht Unordnung. Struktur und Deployment sind getrennte Entscheidungen.
- Der modulare Monolith ist für die meisten Teams die richtige Antwort — er liefert die Grenzen ohne die Verteilung.
- Erzwinge die Grenzen maschinell. Ordner allein halten keine zwei Jahre.
- Ein falscher Schnitt kostet im Monolithen ein Refactoring, in Microservices eine Migration.
- Rechne die Betriebskosten der Verteilung ehrlich ein — verteilte Transaktionen, Tracing, Vertragstests, lokale Umgebung.
Mein Rat für den Einstieg: Zieh die Modulgrenzen, bevor du über Dienste sprichst, und setz zwei Architekturtests auf, die sie durchsetzen. Wenn die Grenzen nach einem halben Jahr noch halten, hast du die Grundlage für eine Zerlegung — und wenn nicht, hast du den teuren Fehler zum Preis eines Refactorings gemacht statt zum Preis einer Migration.
Ressourcen
- Microservices – Martin Fowler – die einflussreichste Definition des Begriffs
- MonolithFirst – warum der Monolith der bessere Startpunkt ist
- Modular Monolith – ausführliche Einführung in die Zwischenform
- microservices.io – Musterkatalog von Chris Richardson