- Wenn Code in frühen Startups vorschnell in Microservices aufgeteilt wird, führt das zu einem erheblichen Produktivitätsverlust im Team und zu mehr Komplexität
- Eine monolithische Architektur bietet einfache Deployments, schnelle Veröffentlichung neuer Features und optimiert das Überleben durch effiziente Zusammenarbeit
- Microservices bieten die Vorteile der Aufteilung nur dann, wenn große Skalierung, unterschiedliche Workloads oder separate Runtime-Anforderungen vorliegen
- Übermäßige Service-Aufteilung, eine Flut an Repositories, instabile lokale Entwicklungsumgebungen und ein uneinheitlicher Tech-Stack führen zu geringerem Tempo und sinkender Teammoral
- Startups sollten mit einem Monolithen beginnen und nur dann vorsichtig aufteilen, wenn klare Engpässe entstehen
Einleitung und Hintergrund
- Das Überleben eines Startups wird durch schnelle Iteration, die Bereitstellung neuer Features und die Schaffung von Nutzerwert bestimmt
- Die grundlegende Architektur eines Projekts, der Tech-Stack und die Wahl der Programmiersprache beeinflussen das Tempo des Teams
- Die frühe Einführung von Microservices wirkt offiziell zwar elegant, führt in der Praxis jedoch zu Produktivitätsverlust, unvollständigen Services und übermäßiger Komplexität
- Datenpunkte: Es entstehen vielfältige Entwicklungskosten durch Service-Orchestrierung, Docker-/Skript-Probleme, dupliziertes CI/CD, Kopplung zwischen Services, Observability-Kosten und verteilte Tests
- Statt vorschnell in eine komplexe Architektur zu gehen, wird die Bedeutung einer pragmatischen Architektur betont
Die Stärken des Monolithen
- Ob SaaS oder einfacher Datenbank-Wrapper: Mit der Zeit wird eine App komplexer, aber eine monolithische Architektur bleibt leichter einfach und flexibel zu halten
- Deployments sind einfach, es gibt starke Unterstützung durch populäre Frameworks (Django, ASP.Net, Nest.js usw.) und große Vorteile aus der Open-Source-Community
- Praxisbeispiel: Ein Immobilien-Startup konnte mit einem Laravel-Monolithen zahlreiche Third-Party-Integrationen und Feature-Erweiterungen problemlos umsetzen
- Ohne komplexe Infrastruktur einzuführen oder in Microservices aufzuteilen, konnte man sich auf die Erfüllung von Geschäftsanforderungen und Erwartungen konzentrieren
- Lehre: Architektonische Einfachheit hilft dem Team, sich auf Deployments zu konzentrieren; solange die interne Modularisierung nicht scheitert, ist auch Skalierung ausreichend möglich
Sind Microservices immer die beste Wahl?
- Viele Engineers halten Microservices für die Musterlösung, doch in Wirklichkeit spielen sie ihre Stärken nur bei besonderen Gründen wie Skalierung aus
- In kleinen Teams, bei kleinem Umfang und in Phasen schneller Veränderungen führen sie eher zu duplizierter Infrastruktur, langsamer lokaler Entwicklung und längeren Iterationszyklen
- Auch Unternehmen wie Segment haben einen Wechsel aufgrund ineffizienter Strukturen erlebt
- Lehre: Microservices sind ein Werkzeug zur Beseitigung von Engpässen, kein Template für die Anfangsphase
Warum Microservices besonders in der Frühphase scheitern
1. Willkürliche Service-Grenzen
- Der Versuch, Services anhand von Business-Logik aufzuteilen, indem man sich an Domain-driven Design oder Clean-Architecture-Theorien orientiert, führt dazu, dass die tatsächliche Logik und die Service-Grenzen nicht sauber zusammenpassen
- Beispiel: Die Trennung von Benutzern, Authentifizierung und Berechtigungen erhöht die Deployment-Komplexität und den Schwierigkeitsgrad der API-Entwicklung
- Eine Aufteilung in einer Phase ohne reale Engpässe macht das System instabiler und langsamer
- Es ist effektiver, mit internen Flags oder Toggles eine spätere Aufteilung zu simulieren und organisch nach sinnvollen Grenzen zu suchen, statt übereilt Infrastrukturarbeit zu betreiben
- Lehre: Entscheidungen zur Aufteilung sollten auf realen Engpässen beruhen, nicht auf Theorie
2. Zu viele Repositories und zu viel Infrastruktur
- Code-Stil, Tests, Konfigurationen, Dokumentation und CI/CD vervielfachen sich mit der Anzahl der Services
- Mit einer Monorepo-Struktur lässt sich alles an einem Ort verwalten, was die Code-Konsistenz und die Zusammenarbeit verbessert
- Im Node.js-Umfeld erleichtern Tools wie
nx oder turborepo das Management von Abhängigkeiten und Builds zwischen internen Services
- Nachteile sind komplexe Abhängigkeitsbeziehungen, nötiges CI-Performance-Tuning und der Bedarf an schnelleren Build-Tools
- Auch im Go-Ökosystem kann man anfangs mit einem einzigen Workspace arbeiten und erst bei wachsender Größe über eine Modultrennung nachdenken
- Lehre: Kleine Teams können mit Monorepo und gemeinsamer Infrastruktur Zeit gewinnen
3. Instabile lokale Entwicklungsumgebung
- Zu lange lokale Startzeiten, komplexe Skripte und systemabhängige Abhängigkeiten führen zu verzögertem Onboarding und sinkender Produktivität
- Fehlende Dokumentation, Kompatibilitätsprobleme und OS-spezifische Hacks (z. B. macOS-only-Skripte) werden zu Hindernissen
- In einem Projekt wurde die Docker-Komplexität durch einen Node.js-Proxy reduziert, wodurch die Onboarding-Zeit für Entwickler sank
- Lehre: Wenn die App nur auf einem Betriebssystem läuft, hängt die Produktivität des Teams am Ende von der Zuverlässigkeit eines einzigen Laptops ab
4. Uneinheitlicher Tech-Stack
- Node.js und Python eignen sich gut für schnelle Iteration, aber in einer Microservice-Umgebung treten häufig Probleme durch Unterschiede bei Build und Runtime auf
- Go hat Vorteile bei statischen Binärdateien, schnellen Builds und einfacherem Betrieb
- Die Wahl des Tech-Stacks sollte früh sorgfältig getroffen werden; falls nötig, kann ein Mischbetrieb verschiedener Sprachen über Protokolle wie gRPC ermöglicht werden
- Ohne besondere Anforderungen wie ML oder ETL erhöht ein gemischter Stack meist nur die Komplexität
- Lehre: Wählt einen Stack, der zur Realität des Teams passt, nicht zu seinen Träumen
5. Versteckte Komplexität: Kommunikation und Monitoring
- Bei Microservices sind Service Discovery, API-Versionierung, verteiltes Tracing und zentrales Log-Management unverzichtbar
- Das Nachverfolgen von Bugs und Ausfällen ist im Monolithen oft nur ein Stacktrace, in verteilten Umgebungen jedoch deutlich komplexer
- Wenn man es richtig machen will, braucht man spezialisierte Tools wie OpenTelemetry und den Aufbau eines vollständigen Observability-Stacks
- Man sollte erkennen, dass verteilte Systeme eine verpflichtende Zusatzinvestition in weitere Engineering-Herausforderungen bedeuten
Wann Microservices sinnvoll sind
- Workload-Isolierung: Das Auslagern bestimmter asynchroner Aufgaben wie Bildverarbeitung oder OCR kann effizient sein
- Ungleichgewicht bei Skalierungsanforderungen: Wenn Web-API und ML-Workloads unterschiedliche Hardware- und Betriebsanforderungen haben, ist eine getrennte Aufteilung sinnvoll
- Bedarf an anderer Runtime: Komponenten wie Legacy-C++-Code, die runtime-seitig nicht zum Hauptsystem passen, können als separater Service betrieben werden
- Beispiele aus großen Engineering-Organisationen (z. B. Uber) zeigen, dass dies nur bei klarer organisatorischer Notwendigkeit und ausgereiften Betriebsfähigkeiten geeignet ist
- Selbst in kleinen Teams kann eine Trennung in seltenen Fällen praktisch sein, etwa bei externen Analyse-Services mit einfacher Verwaltung
- Lehre: Setzt Microservices nur dort ein, wo der praktische Nutzen der Aufteilung eindeutig ist
Praxisleitfaden für Startups
- Startet zunächst mit einem Monolithen und arbeitet mit bewährten Frameworks fokussiert an der eigentlichen Aufgabe
- Ein einziges Repository ist für frühe Teams bei Betrieb, Verwaltung und Sicherheit oft vorteilhafter
- Eine vereinfachte lokale Entwicklungsumgebung ist wichtig; wenn sie schwierig ist, sind ausführliche Anleitungen und Videos Pflicht
- Früh in CI/CD investieren, um wiederkehrende Arbeit zu automatisieren und die mentale Last im Team zu senken
- Nur bei klar auftretenden Engpässen selektiv aufteilen; sonst auf Modularisierung und bessere Tests innerhalb des Monolithen konzentrieren
- Oberstes Ziel ist der Erhalt der Entwicklungsgeschwindigkeit
- Lehre: Mit Einfachheit beginnen und passend zum tatsächlichen Bedarf an Trennung skalieren
Wenn ihr Microservices unbedingt einsetzen müsst
- Tech-Stack bewerten und in Developer-Experience-Tools investieren: Automatisierung pro Service, klare Skripte und Tools für zentrales Deployment-Management sind nötig
- Zuverlässige Service-Kommunikationsprotokolle und Standardisierung: Zusätzliche Implementierungsaspekte wie konsistente Message-Schemas, Dokumentation und Fehlerbehandlung müssen berücksichtigt werden
- Test-Infrastruktur stabilisieren: Unit-, Integrations- und E2E-Tests müssen passend zur Service-Aufteilung skalieren
- Gemeinsame Bibliotheken sorgfältig abwägen: Gemeinsamer Code für Observability und Kommunikation sollte minimal gehalten werden, um häufige Rebuilds aller Services zu vermeiden
- Observability früh einführen: Bereits grundlegende Logging-Werkzeuge wie strukturierte JSON-Logs und Correlation IDs sollten vorhanden sein
- Zusammengefasst ist es wichtig, bei akzeptierter Komplexität mit voller Konsequenz ein System zu entwerfen, das beherrschbar bleibt
Fazit
- Eine vorschnelle Einführung von Microservices hinterlässt vor allem Belastung, daher sollte Einfachheit oberste Priorität haben
- Ohne klaren Schmerzpunkt sollte man nicht aufteilen; entscheidend ist die Perspektive, nur die minimale Komplexität hinzuzufügen, die für Überleben und Wachstum nötig ist
- Erst überleben, dann skalieren
10 Kommentare
Ich stimme der ursprünglichen Aussage insgesamt zu.
Ich denke, es ist eine Frage der Erfahrung innerhalb der Organisation.
Man kann es sich so vorstellen, als würde man erst Essen aus einem Foodtruck verkaufen und dann zu einem Restaurant werden.
Von Anfang an Arbeitsteilung und Spezialisierung einzuplanen, ist kaum möglich, weil den Beteiligten dafür schlicht die notwendige Erfahrung fehlt.
Ich denke, Startups sollten Wege mit geringeren Kosten wählen, um ihre Überlebenszeit zu verlängern. Microservices sind absolut nicht billig. In der Praxis verursachen sie im realen Einsatz beträchtliche Kosten. Wenn möglich, ist es aus meiner Sicht ein Weg, mit geringeren Kosten ähnliche Effekte zu erzielen, eine Architektur zu entwerfen, die zum eigenen Service passt.
Ich sage nicht, dass Microservices schlecht sind. Es ist ein Modell, das hohe Kosten erfordert.
Ich denke, es reicht völlig, wenn man nur zwei Dinge hat: einen rein synchronen Monolithen und einen rein asynchronen Monolithen ... Die Einführung von Microservices hängt meiner Ansicht nach letztlich vom Umfang der Tabellen ab, die in der DB verwaltet werden müssen. Wenn es absurd viele und komplexe Tabellen gibt, sollte man über MSA nachdenken; wenn es einfach ist, ist ein Monolith genau richtig.
Wenn all diese Wellen vorübergezogen sind, wie wird die Nachwelt sich an diese Generation erinnern?
Damals war es wieder die Welle jener Zeit ...
Ich denke, dass Microservices auch in Startups viele Vorteile haben. Vor allem die Vorteile eines Monorepos kann ich wirklich empfehlen.
Ich stimme zu, dass es im Zeitalter der KI-Entwicklung unverzichtbar ist, in kleinen Einheiten mit klar abgegrenzter Verantwortung zu implementieren.
Das wurde in den Kommentaren schon kurz angesprochen, aber die Beam/OTP-Welt wirkt in dieser Hinsicht ziemlich flexibel und gut. Im Fall von Gleam ist durch die Kombination der guten Syntax von Go und Rust mit der Stabilität von Beam eine ziemlich beeindruckende Sprache entstanden. Ich würde sie nach und nach gern einmal in kleineren Projekten einsetzen.
Wenn man Teams wahllos aufteilt, wird schon das Zusammenkommen, um Meinungen auszutauschen, zu einer enormen Aufgabe.
Hacker-News-Kommentare