Microservices oder Monolith? Warum wir Microservices nur selten empfehlen
Wer heute eine neue Plattform plant, hört früher oder später das Wort Microservices. Es klingt nach modern, skalierbar und zukunftssicher. Wir empfehlen Microservices trotzdem nur selten. Das liegt nicht an der Technik. Microservices lösen vor allem ein Problem der Organisation, nämlich die Abstimmung vieler Entwicklungsteams. Dieses Problem haben die allermeisten Unternehmen, für die wir arbeiten, nicht. Den Mehraufwand zahlen sie trotzdem.
Kurz gesagt
- Microservices sind die technische Form einer Organisationsentscheidung: Viele Teams sollen unabhängig voneinander ausliefern können.
- Der Preis dafür ist dauerhaft: Netzwerk statt Funktionsaufruf, verteilte Daten, mehrfacher Betrieb, schwierigere Fehlersuche.
- Für fast alle Projekte, die wir sehen, ist eine einzige, sauber gegliederte Anwendung die bessere Wahl: ein sogenannter modularer Monolith.
- Braucht ein Teil später wirklich ein Eigenleben, lässt er sich aus einer gut gegliederten Anwendung herauslösen. Umgekehrt ist der Weg deutlich teurer.
Was Microservices eigentlich lösen
Den Begriff haben James Lewis und Martin Fowler 2014 bekannt gemacht. Gemeint ist eine Anwendung, die aus vielen kleinen Diensten besteht. Jeder läuft für sich, wird für sich ausgeliefert und hält oft seine eigenen Daten.
Schon in diesem Grundlagenartikel geht es auffällig viel um Teams. Die Autoren berufen sich auf eine Beobachtung von Melvin Conway aus dem Jahr 1968: Systeme spiegeln die Kommunikationsstruktur der Organisation, die sie baut. Ihre Empfehlung lautet deshalb, Teams entlang fachlicher Aufgaben zu schneiden, und jedes Team verantwortet seinen Dienst bis in den Betrieb. Die Beratung Thoughtworks hat daraus das „Inverse Conway Maneuver“ gemacht: Man baut die Organisation um, damit die gewünschte Architektur entsteht.
Sam Newman, Autor des Standardwerks „Building Microservices“, nennt als eigentliches Ziel die unabhängige Auslieferung: Ein Team ändert seinen Teil und bringt ihn live, ohne auf die anderen zu warten. Das ist wertvoll, wenn viele Teams sich sonst gegenseitig blockieren. Arbeitet ein einzelnes Team an der Anwendung, gibt es niemanden, auf den es warten müsste.
Microservices lohnen sich also dort, wo so viele Teams an einem Produkt arbeiten, dass das gemeinsame Release zum Engpass wird. Das ist eine Frage der Organisation, nicht der Technik.
Woher Microservices kommen
Die bekannten Vorbilder sind Unternehmen mit sehr großen Entwicklungsabteilungen.
- Amazon: Anfang der 2000er-Jahre soll Jeff Bezos angeordnet haben, dass alle Teams ihre Daten und Funktionen nur noch über Schnittstellen anbieten. Überliefert ist das durch einen Text des früheren Amazon-Entwicklers Steve Yegge. Es war eine Anweisung an eine Organisation mit sehr vielen Teams.
- Netflix: Nach einem schweren Datenbankschaden 2008 konnte Netflix drei Tage lang keine DVDs verschicken. Danach baute das Unternehmen um, auf verteilte Systeme in der Cloud und von einer großen Anwendung zu Hunderten kleiner Dienste. Der Umbau dauerte nach eigener Aussage sieben Jahre.
- Uber: Der Fahrdienst betrieb 2020 rund 2.200 kritische Microservices. Die Folge beschreibt Uber selbst: Für eine einfache Funktion muss oft über mehrere Dienste hinweg gearbeitet werden, die verschiedenen Personen und Teams gehören. Uber hat darauf reagiert, indem es die Dienste in größere fachliche Bereiche gruppiert hat.
David Heinemeier Hansson, Erfinder des Web-Frameworks Ruby on Rails, hat das 2016 so zusammengefasst: Was für Organisationen sinnvoll ist, die um Größenordnungen größer sind als Ihre, ist für Sie oft genau das Falsche.
Der Mehraufwand ist real
Microservices verschieben Komplexität aus dem Code in die Verbindungen zwischen den Diensten. Diese Arbeit fällt nicht einmal an, sondern bleibt, solange das System läuft.
- Aus Funktionsaufrufen werden Netzwerkaufrufe. Was vorher innerhalb einer Anwendung lief, geht jetzt über das Netz. Das ist langsamer und kann ausfallen. Die Annahme, das Netz sei zuverlässig und schnell, gehört zu den bekannten Trugschlüssen verteilter Systeme.
- Daten liegen verteilt. Eine Bestellung, die Lager, Zahlung und Versand betrifft, lässt sich nicht mehr in einem Schritt sicher speichern. Stattdessen braucht es mehrstufige Abläufe mit ausprogrammierten Ausgleichsschritten für den Fehlerfall, und die Daten stimmen erst nach einer Weile überein.
- Betrieb und Auslieferung gibt es mehrfach. Jeder Dienst braucht seine eigene Auslieferung, Überwachung und Wartung. Martin Fowler nennt als Voraussetzungen unter anderem, Server binnen Stunden bereitzustellen, eine Überwachung, die Probleme schnell erkennt, und schnelles, automatisiertes Ausliefern.
- Fehlersuche wird schwerer. Ein Fehler zeigt sich in einem Dienst und entsteht in einem anderen. Viele dieser Fehler treten erst im Zusammenspiel im Live-Betrieb auf, nicht in der Testumgebung.
- Falsche Grenzen sind teuer. Wer am Anfang eines Projekts in Dienste schneidet, kennt die fachlichen Grenzen oft noch nicht gut genug. Liegen sie falsch, betrifft jede Änderung mehrere Dienste. Das kann nach Sam Newman schlechter sein als eine einzige Anwendung.
Fowler spricht vom „Microservice-Aufschlag“: Microservices erhöhen Kosten und Risiko eines Projekts. Sein Rat ist, sie erst in Betracht zu ziehen, wenn ein System als einzelne Anwendung nicht mehr beherrschbar ist. Newman sagt es drastischer: Wie schmerzhaft und teuer der Betrieb von Microservices ist, merke man erst, wenn sie live sind.
Der ungünstigste Fall ist der verteilte Monolith: Dienste, die nur gemeinsam ausgeliefert werden können. Er hat alle Kosten eines verteilten Systems und keinen seiner Vorteile. Sam Newman warnt ausdrücklich davor. Ben Christensen, damals bei Facebook, hat schon 2016 beschrieben, wie etwa gemeinsam genutzter Code Dienste so eng aneinander bindet.
Was andere erlebt haben
- Segment (2018): Der Datendienst hatte über 140 Microservices, einen je angebundenem Zielsystem. Laut dem Rückblick des Teams verbrachten drei Vollzeit-Entwickler den größten Teil ihrer Zeit damit, das System am Laufen zu halten. Segment führte die Dienste zu einem zusammen. Danach liefen die Tests deutlich schneller, und ein einzelner Entwickler konnte in Minuten ausliefern. Das Team nennt auch die Nachteile, etwa dass ein Fehler jetzt den ganzen Dienst treffen kann. Dazu gehört: Segment hatte sehr fein geschnitten.
- Istio (2020): Das Open-Source-Projekt hat seine Steuerung aus mehreren Diensten zu einem einzigen Programm zusammengelegt. Die Begründung: Die Bestandteile wurden ohnehin immer in derselben Version zur selben Zeit ausgeliefert. Die Vorteile getrennter Dienste kamen also nie zum Tragen.
- Amazon Prime Video (2023): Ein Team verlegte einen Überwachungsdienst von einer verteilten, serverlosen Lösung in einen einzigen Prozess. Die Kosten sanken laut Bericht von InfoQ um 90 Prozent. Zur Einordnung: Kritiker wie der frühere Netflix-Architekt Adrian Cockcroft betonen, dass es hier eher um serverlose Bausteine gegen Container ging und der Dienst selbst weiter ein eigenständiger Dienst ist. Der Fall zeigt trotzdem, dass Verteilung ihren Preis hat.
- Shopify: Eine der größten Handelsplattformen der Welt läuft im Kern bewusst als eine Anwendung mit streng getrennten fachlichen Bereichen, an der über die Jahre mehr als tausend Entwickler gearbeitet haben. 2020 umfasste sie über 2,8 Millionen Zeilen Code. Einzelne Teile lagert Shopify nur mit gutem Grund aus, weil ein verteiltes System die Komplexität deutlich erhöht.
Was wir stattdessen empfehlen: eine Anwendung mit klaren Grenzen
Unser Standard ist der modulare Monolith: eine Anwendung, eine Auslieferung, eine Datenbank. Innen ist sie in fachliche Module geschnitten, die nur über festgelegte Schnittstellen miteinander sprechen. Sam Newman nennt diese Bauweise „stark unterschätzt“ und sagt, er habe der Hälfte seiner Kunden von Microservices abgeraten.
Damit die Grenzen im Alltag halten, folgen wir in unserer Standardarchitektur den Regeln von Feature-Sliced Design (FSD). Die Methode stammt aus der Frontend-Entwicklung. Die Grundsätze übertragen wir auf die ganze Anwendung:
- Schnitt nach Fachlichkeit, nicht nach Technik. Alles, was zu einer fachlichen Aufgabe gehört, etwa zur Bestellung, liegt an einem Ort: Oberfläche, Datenzugriff, Regeln und Tests.
- Abhängigkeiten nur in eine Richtung. Jede Ebene darf nur auf darunterliegende Ebenen zugreifen, von den Seiten über die Funktionen bis zu gemeinsamen Grundlagen. Zwei Funktionen greifen nicht quer ineinander. Was beide brauchen, wandert eine Ebene tiefer.
- Jeder Bereich hat eine öffentliche Schnittstelle. Sie ist ein Vertrag mit dem Rest der Anwendung. Was dahinter liegt, kann sich ändern, ohne dass andere Teile brechen.
- Unsere Prüffrage: Lässt sich ein Funktionsbereich entfernen, ohne dass ein anderer bricht? Wenn nicht, ist der Schnitt falsch.
Solche Regeln lassen sich automatisch prüfen, zum Beispiel mit Importregeln, die bei jeder Änderung anschlagen. Shopify macht das für seine Anwendung mit einem eigenen Werkzeug, Packwerk.
Der Vorteil für Sie: Sie bekommen die Ordnung, die man sich von Microservices verspricht, ohne deren Betriebsaufwand. Und Sie halten sich den Weg offen. Bekommt ein Modul später wirklich eigene Anforderungen, lässt es sich entlang seiner Schnittstelle herauslösen, Schritt für Schritt nach dem Strangler-Fig-Muster, das wir auch für die Modernisierung von Altsystemen nutzen. Martin Fowler hat beobachtet, dass fast alle erfolgreichen Microservice-Projekte so begonnen haben: als Anwendung, die zu groß wurde und dann aufgeteilt wurde. Von Systemen, die gleich als Microservices gebaut wurden, sind nach seiner Erfahrung fast alle in ernste Schwierigkeiten geraten.
Und unsere Referenzarchitektur?
Unsere Referenzarchitektur für den Mittelstand besteht aus vier Bausteinen: Next.js für die Oberfläche, Strapi für Inhalte und Anbindungen, Shopware 6 für den Handel und Meilisearch für die Suche. Das ist keine Microservice-Architektur. Es sind vier bewährte Produkte, und jedes hat eine klar abgegrenzte Aufgabe, die es für sich gut kann. Wir zerlegen unseren eigenen Code nicht in viele kleine Dienste. Die Oberfläche und die Anbindungen sind jeweils eine gut gegliederte Anwendung nach den Regeln oben.
Wann wir doch zu Microservices raten
Microservices sind kein Fehler, sie sind ein Werkzeug für bestimmte Lagen. Martin Fowler schreibt selbst, dass viele Teams mit wachsender Größe und Komplexität mit Microservices besser fahren. Wir raten dazu, wenn mehrere dieser Punkte zutreffen:
- Mehrere Teams arbeiten am selben Produkt und blockieren sich beim Ausliefern gegenseitig.
- Ein Teil hat deutlich andere Anforderungen an Last, Verfügbarkeit oder Sicherheit als der Rest.
- Die fachlichen Grenzen sind über längere Zeit stabil und gut verstanden.
- Der Betrieb ist darauf eingestellt: automatisierte Bereitstellung, Überwachung, schnelles Ausliefern.
Eine allgemein anerkannte Teamgröße, ab der sich Microservices lohnen, gibt es nicht. Entscheidend ist, ob die Abstimmung zwischen Teams heute tatsächlich der Engpass ist.
Es gibt auch eine ernstzunehmende Gegenstimme. Stefan Tilkov hielt es 2015 für falsch, mit einem Monolithen anzufangen, wenn ein verteiltes System das Ziel ist, weil sich ein gewachsener Monolith schwer zerlegen lässt. Wir teilen die Sorge und ziehen eine andere Konsequenz: Wir ziehen klare Modulgrenzen von Anfang an, damit sich ein Teil später herauslösen lässt.
Fragen, die Sie Ihrem Dienstleister stellen können
Wenn Ihnen ein Angebot mit Microservices vorliegt, helfen diese Fragen bei der Einordnung:
- Wie viele Teams werden an der Lösung arbeiten, und müssen sie unabhängig voneinander ausliefern?
- Welches konkrete Problem löst die Aufteilung in Dienste, das eine gut gegliederte Anwendung nicht löst?
- Wer betreibt und überwacht die Dienste nach dem Start, und mit welchem laufenden Aufwand?
- Was passiert mit einer Bestellung, wenn ein beteiligter Dienst gerade nicht erreichbar ist?
- Wie wird sichergestellt, dass die Grenzen zwischen den Modulen auch nach Jahren noch halten?
Fazit
Microservices beantworten eine Organisationsfrage großer Entwicklungsabteilungen. Für die meisten Unternehmen ist eine einzige, sauber gegliederte Anwendung schneller gebaut, günstiger im Betrieb und leichter zu ändern. Für Standardaufgaben setzen wir bewährte Produkte ein. Einzelne Teile lösen wir erst heraus, wenn es dafür einen konkreten Grund gibt.
Sie stehen vor einer Architekturentscheidung oder haben ein Angebot mit Microservices auf dem Tisch? Sprechen Sie uns an. Wir schauen es uns gemeinsam mit Ihnen an.
Quellen
- James Lewis, Martin Fowler: Microservices, 25.03.2014
- Melvin E. Conway: How Do Committees Invent?, Datamation, April 1968
- Thoughtworks Technology Radar: Inverse Conway Maneuver, seit 2014
- Thomas Betts: Decomposing a Monolith Does Not Require Microservices (Sam Newman, QCon London), InfoQ, 13.05.2020
- Tim Anderson: Microservices should be a last resort (Sam Newman), The Register, 04.03.2020
- Sam Newman: Microservices for Greenfield?, 07.04.2015
- Steve Yegge: Google Platforms Rant, 2011
- Netflix: Completing the Netflix Cloud Migration, 12.02.2016
- Adam Gluck: Introducing Domain-Oriented Microservice Architecture, Uber Engineering, 23.07.2020
- David Heinemeier Hansson: The Majestic Monolith, 29.02.2016
- Wikipedia: Fallacies of distributed computing (L. Peter Deutsch, James Gosling)
- Chris Richardson: Pattern: Saga, microservices.io
- Martin Fowler: Microservice Prerequisites, 28.08.2014
- Martin Fowler: Microservice Premium, 13.05.2015
- Martin Fowler: MonolithFirst, 03.06.2015
- Martin Fowler: Strangler Fig
- Jan Stenberg: Services, Microservices and the Distributed Monolith (Ben Christensen), InfoQ, 2016
- Alexandra Noonan: Goodbye Microservices, Segment, 10.07.2018
- Craig Box: Introducing istiod, Istio, 19.03.2020
- Rafał Gancarz: Prime Video Switched from Serverless to EC2 and ECS to Save Costs, InfoQ, 03.05.2023
- The Stack: Prime Video monolith debate, Adrian Cockcroft, Mai 2023
- Kirsten Westeinde: Deconstructing the Monolith, Shopify Engineering, 21.02.2019
- Philip Müller: Under Deconstruction: The State of Shopify's Monolith, Shopify Engineering, 16.09.2020
- Maple Ong: Enforcing Modularity in Rails Apps with Packwerk, Shopify Engineering, 23.09.2020
- Feature-Sliced Design: Overview, Layers, Public API
- Stefan Tilkov: Don't start with a monolith, 09.06.2015