Die Ära der „Microservice-Reue“: Warum Teams leise zum Monolithen zurückkehren
Warum Startups und Entwicklerteams leise zum modularen Monolithen zurückkehren, nachdem sie die versteckten Kosten verfrühter Microservices erlebt haben.
Eine Zeit lang wirkten Microservices wie der selbstverständliche nächste Schritt für jedes ernsthafte Softwareprodukt.
Sobald ein Startup zu wachsen begann, drehte sich das Architekturgespräch früher oder später darum, die Anwendung in kleinere Services aufzuteilen. Die Authentifizierung wurde ein eigener Service. Payments wurden abgetrennt. Benachrichtigungen wanderten woandershin. Und ehe man sich versah, liefen hinter einem Produkt, das als relativ einfache Anwendung angefangen hatte, erstaunlich viele Services.
Und ehrlich gesagt gab es dafür gute Gründe.
Microservices lösen echte Probleme. Mit ihnen können Teams Teile eines Systems unabhängig deployen, bestimmte Workloads skalieren, ohne gleich alles andere mitzuskalieren, und größeren Entwicklerteams mehr Verantwortung für einzelne Teile eines Produkts geben.
Für Unternehmen, die in großem Maßstab arbeiten, kann diese Trennung enorm nützlich sein.
Das Problem beginnt, wenn die Architektur vor dem Problem da ist.
Ein Startup mit fünf Leuten und ein paar tausend Nutzern hat nicht dieselben Architekturanforderungen wie ein Unternehmen mit Hunderten Engineers und Millionen Requests pro Tag. Trotzdem passiert es erstaunlich leicht, das kleinere Produkt so zu bauen, als wäre diese Zukunft schon angekommen.
Genau da beginnt die Microservice-Reue.
Microservices sind nicht das Problem
Eins vorweg: Das hier ist kein Plädoyer gegen Microservices.
Sie sind nicht schlecht. In der richtigen Situation sind sie extrem nützlich.
Das Problem ist, sie einzuführen, nur weil sie sich wie der „richtige“ Weg anfühlen, eine moderne Anwendung zu bauen – und nicht, weil das Produkt sie tatsächlich braucht.
Stell dir eine kleine Anwendung mit Authentifizierung, Payments, Nutzerprofilen und Benachrichtigungen vor.
Du könntest aus jedem dieser Teile einen eigenen Service machen. Auf einem Architekturdiagramm sieht das vielleicht sauber und gut organisiert aus.
Aber jetzt braucht jeder Service einen Deployment-Prozess, Monitoring, Logging, Konfiguration, Authentifizierung, Fehlerbehandlung und Dokumentation.
Was ein Funktionsaufruf innerhalb derselben Anwendung hätte sein können, ist jetzt ein Netzwerk-Request.
Und Netzwerk-Requests können fehlschlagen.
Ein Service kann in einen Timeout laufen. Eine Datenbank kann kurzzeitig nicht erreichbar sein. Ein Request kann wiederholt werden. Ein Service kann eine Änderung deployen, bevor ein anderer bereit dafür ist. Plötzlich hast du es mit Problemen verteilter Systeme zu tun, die es schlicht nicht gab, solange alles in einer Anwendung lebte.
Das Produkt ist nicht unbedingt komplizierter geworden.
Die Architektur schon.
Die versteckten Kosten von „Skalierbarkeit“
Wenn Leute über Skalierbarkeit reden, meinen sie meistens Traffic.
Hält das System zehnmal mehr Nutzer aus? Kann es mehr Requests verarbeiten? Lässt sich ein bestimmter Teil der Anwendung unabhängig skalieren?
Das sind wichtige Fragen, aber es gibt noch eine andere Art von Skalierbarkeit, die man leicht übersieht: wie gut das Team selbst das System verstehen und verändern kann.
Ein System, das Millionen Requests verkraftet, bei dem man aber drei Tage braucht, um es zu verstehen, bevor man eine kleine Änderung machen kann, ist nicht gerade angenehm zu bearbeiten.
Das ist ein Grund, warum der modulare Monolith wieder attraktiv wirkt.
Statt sofort alles in unabhängige Services aufzuteilen, kann ein Team bei einer Anwendung bleiben und trotzdem klare Grenzen darin ziehen. Authentifizierung, Abrechnung, Nutzer, Benachrichtigungen und andere Domänen können eigene Module und Zuständigkeiten haben, ohne dass jede einen eigenen Service samt Infrastruktur braucht.
Du bekommst Struktur, ohne sofort den vollen Betriebsaufwand verteilter Systeme zu zahlen.
Und wenn eines dieser Module irgendwann groß genug wird, dass sich ein eigener Service lohnt, kannst du es später herauslösen.
Diese Flexibilität zählt.
Store-fertige Screenshots in Minuten gestalten – kostenlos, ohne Wasserzeichen.
Launch Shots kannst du kostenlos nutzen. Alle Vorlagen (110+), über 220 Geräterahmen plus 3D-Mockups, KI-Übersetzung und direkter Upload in App Store Connect und die Google Play Console. Keine Kreditkarte nötig.
Kostenlos loslegen →Du musst die Zukunft nicht vorhersagen
Eine der einfachsten Arten, ein Startup zu over-engineeren, ist, um Probleme herum zu bauen, die noch gar nicht aufgetreten sind.
„Vielleicht haben wir mal Millionen Nutzer.“
„Vielleicht haben wir mal mehrere Entwicklerteams.“
„Vielleicht müssen wir diese Komponente unabhängig skalieren.“
„Vielleicht wechseln wir später die Datenbank.“
All das ist möglich.
Aber möglich heißt nicht wahrscheinlich, und wahrscheinlich heißt nicht, dass du es heute lösen musst.
Die Architektur eines Startups sollte vor allem auf die Probleme reagieren, die das Team tatsächlich hat – nicht auf eine ausgedachte Version des Unternehmens in fünf Jahren.
Wenn das System irgendwann aufgeteilt werden muss, kannst du es aufteilen, sobald der Grund klar ist.
Bis dahin kann es die Entwicklung beschleunigen, das Debugging erleichtern und das ganze System verständlicher machen, wenn alles zusammenbleibt.
Das heißt nicht, zukünftiges Wachstum zu ignorieren.
Es heißt, zu akzeptieren, dass du wahrscheinlich noch nicht genau weißt, wie dieses Wachstum aussehen wird.
Und das ist okay.
Jeder Service bringt eine weitere Verantwortung mit
Man schaut leicht auf eine Microservice-Architektur und sieht eine Sammlung kleiner, schön getrennter Bausteine.
Was dabei übersehen wird: Jeder dieser Bausteine hat Betriebskosten.
Ein Service muss deployt werden. Er braucht Monitoring. Er braucht Logs. Er braucht Alerts. Er braucht Konfiguration. Jemand muss verstehen, was passiert, wenn er ausfällt. Jemand muss nachforschen, wenn seine Latenz plötzlich steigt.
Und jetzt stell dir das für zehn Services vor.
Dann für zwanzig.
Dann für fünfzig.
Für eine große Organisation kann sich dieser Overhead absolut lohnen. Die Unabhängigkeit zwischen Teams und Systemen kann genug Wert schaffen, um die ganze Komplexität zu rechtfertigen.
Für ein kleines Team kann es dagegen zur Ablenkung werden.
Statt Zeit in die Verbesserung des Produkts zu stecken, verbringen Entwickler dann einen großen Teil ihrer Zeit damit, die Maschinerie zu pflegen, die die Architektur am Laufen hält.
Und das ist einer der weniger offensichtlichen Kosten von Microservices.
Der Code selbst ist vielleicht gar nicht besonders schwierig.
Es ist alles rund um den Code, was sich nach und nach summiert.
Der modulare Monolith verdient mehr Respekt
Der modulare Monolith liegt irgendwo zwischen den beiden Extremen.
Er ist immer noch eine einzige Anwendung, muss aber keine riesige, verknotete Codebasis sein, in der alles auf alles zugreifen kann.
Die Anwendung lässt sich in logische Module mit klaren Zuständigkeiten und Grenzen aufteilen.
So können Entwickler in getrennten Domänen denken, ohne zwischen jede Domäne eine Netzwerkgrenze zu setzen.
Auch die Entwicklung bleibt relativ einfach. Die Anwendung lokal laufen zu lassen ist leichter. Debugging ist meist geradliniger. Transaktionen lassen sich einfacher handhaben. Ein Deployment erfordert nicht, eine ganze Reihe unabhängiger Services zu koordinieren.
Und es gibt weniger Infrastruktur zu pflegen.
Vor allem heißt ein Start mit einem Monolithen nicht, dass du für immer an ihm festhängst.
Ein gut strukturierter Monolith kann einen späteren Umstieg auf Microservices sogar erleichtern, weil die Grenzen schon existieren.
Wenn das Billing-Modul irgendwann der Teil des Systems wird, der wirklich unabhängig skaliert oder deployt werden muss, kannst du es herauslösen.
Du musst nicht alles herauslösen, nur weil sich ein Teil ändern muss.
Das ist der eigentliche Vorteil guter Grenzen.
Du hältst dir Optionen offen.
Wann ergeben Microservices also wirklich Sinn?
Es gibt keine magische Nutzerzahl, ab der ein Unternehmen plötzlich vom Monolithen zu Microservices wechseln sollte.
Traffic allein reicht für diese Entscheidung nicht.
Microservices werden deutlich überzeugender, wenn verschiedene Teile des Systems wirklich unterschiedliche Skalierungsanforderungen haben, wenn Teams unabhängig deployen müssen, wenn die Domänengrenzen gut verstanden sind oder wenn bestimmte Komponenten komplett andere Technologien oder Infrastruktur brauchen.
Auch die Teamstruktur spielt eine Rolle.
Eine Organisation mit Dutzenden Entwicklerteams hat ganz andere Koordinationsprobleme als ein Startup mit vier Entwicklern.
Die Architektur sollte auf diese Realitäten reagieren.
Wenn du einen Service abspaltest, weil eine Komponente ein echtes Skalierungsproblem verursacht, ist das ein Grund.
Wenn du eine Domäne abtrennst, weil mehrere Teams unabhängig daran arbeiten müssen, ist das ein Grund.
Wenn du es tust, weil „wir es vielleicht irgendwann brauchen“, lohnt es sich vielleicht zu warten.
Die beste Architekturentscheidung ist oft die, die das Problem von heute löst, ohne fünf neue zu schaffen.
Die ausgefeilteste Architektur ist vielleicht die langweilige
Softwareentwicklung neigt dazu, Komplexität zu belohnen.
Ein Diagramm voller Services, Queues, Datenbanken, Event-Busse und Infrastrukturkomponenten kann beeindruckend aussehen.
Aber Nutzer sehen nichts davon.
Sie sehen, ob das Produkt schnell lädt. Sie sehen, ob ihre Daten sicher sind. Sie sehen, ob ein Feature funktioniert, wenn sie es brauchen. Sie sehen, ob sich das Produkt zuverlässig anfühlt.
Genau dafür ist die Architektur letztlich da.
Manchmal heißt das Microservices.
Manchmal heißt es modularer Monolith.
Manchmal heißt es etwas irgendwo dazwischen.
Der Fehler ist die Annahme, dass eine kompliziertere Architektur automatisch ein reiferes Entwicklerteam bedeutet.
Bei guter Architektur geht es nicht darum, wie viele Technologien du in ein System packen kannst.
Es geht darum, etwas zu bauen, das verständlich genug ist, zuverlässig genug läuft und flexibel genug bleibt, um sich zu ändern, wenn sich das Produkt ändert.
Vielleicht ist das der Grund, warum manche Teams zum Monolithen zurückkehren.
Sie geben Skalierbarkeit nicht unbedingt auf.
Sie merken, dass auch Einfachheit eine Form von Skalierbarkeit ist – besonders wenn das, was skalieren muss, nicht nur die Infrastruktur ist, sondern auch das Team, das das Produkt baut.
