5 Punkte von GN⁺ 2025-12-14 | 2 Kommentare | Auf WhatsApp teilen
  • Twilio Segment betrieb Hunderte von Microservices, wechselte aber wegen der Komplexität und des hohen Wartungsaufwands zu einem Single-Service (Monolithen)
  • Anfangs wurden die einzelnen Destination-APIs getrennt, um Fehler zu isolieren und Skalierbarkeit zu erreichen. Als die Zahl der Services jedoch auf über 140 anstieg, nahm der operative Overhead stark zu
  • Die Verwaltung zahlreicher Repositories und Shared Libraries wurde schwierig, und bei Tests sowie Deployments traten Probleme auf, die alle Services betrafen
  • Um das zu lösen, führte das Unternehmen das Centrifuge-System und eine Monorepo-Struktur ein und baute für die Testautomatisierung den Traffic Recorder
  • Dadurch verbesserten sich Entwicklungsgeschwindigkeit und Stabilität deutlich; Twilio Segment setzt den Monolithen weiterhin aus Gründen der Produktivität und operativen Effizienz ein

Einführung von Microservices und ihre Grenzen

  • Twilio Segment setzte für seine Customer-Data-Infrastruktur auf eine Microservices-Architektur und entwarf die Plattform so, dass Services für einzelne Zwecke Ereignisse unabhängig verarbeiten
    • Daten werden an Hunderte von serverseitigen Destinations (z. B. Google Analytics, Optimizely usw.) weitergeleitet
    • Anfangs wurde eine einzelne Queue verwendet, doch bei Ausfällen bestimmter Destinations trat Head-of-Line-Blocking auf, wodurch das gesamte System verzögert wurde
  • Zur Lösung richtete das Unternehmen für jede Destination separate Services und Queues ein und erreichte so Fehlerisolation sowie unabhängige Skalierung
  • Mit wachsender Zahl der Services stiegen jedoch operative Komplexität und Wartungskosten stark an, was die Entwicklung verlangsamte und die Fehlerquote erhöhte

Probleme mit einzelnen Repositories und Shared Libraries

  • Jede Destination verwendet ein anderes API-Format, weshalb benutzerdefinierter Transformationscode nötig war
    • Anfangs wurde alles in einem einzigen Repository verwaltet, doch fehlschlagende Tests wirkten sich auf alles aus, sodass eine Aufteilung der Repositories erfolgte
  • Mit der späteren Ergänzung von mehr als 50 neuen Destinations entstanden über 50 Repositories
    • Für gemeinsame Funktionen wurden Shared Libraries eingeführt, doch Versionsunterschiede und der Aufwand für Deployments nahmen zu
    Anzeige
  • Da sich die Lastmuster je Service unterschieden, waren Auto-Scaling-Einstellungen schwer abzustimmen; in manchen Fällen mussten Operatoren manuell eingreifen

Umstellung auf den Monolithen und Einführung von Centrifuge

  • Es fiel die Entscheidung, mehr als 140 Services in einem einzigen Service zu konsolidieren
    • Um die einzelnen Queues zu ersetzen, wurde das Centrifuge-System entwickelt, das alle Events an einen einzigen Service weiterleitet
    • Centrifuge entwickelte sich später zur Connections-Backend-Infrastruktur von Twilio Segment weiter
  • Mit der Umstellung auf einen Single-Service-Aufbau konnten der operative Aufwand reduziert und die Reaktion auf Störungen vereinfacht werden

Monorepo und Testautomatisierung

  • Der gesamte Code für die Destinations wurde in ein einziges Repository zusammengeführt, und mehr als 120 Abhängigkeiten wurden auf eine einheitliche Version gebracht
    • Das vereinfachte die Versionsverwaltung und verbesserte die Wartungseffizienz
  • Für die Testautomatisierung wurde der Traffic Recorder eingeführt
    • Er zeichnet echte HTTP-Requests und -Responses auf und spielt sie wieder ab, wodurch die Abhängigkeit von externen Netzwerken entfällt
    • Die Testdauer sank von mehreren Minuten auf den Millisekundenbereich, bei deutlich höherer Stabilität
    Anzeige
  • Die Fehlerrate bei Tests sank, und die Produktivität der Entwickler stieg deutlich

Auswirkungen und Trade-offs der monolithischen Struktur

  • Nach der Konsolidierung in einen Single Service verbesserten sich Deployment-Geschwindigkeit und Entwicklungseffizienz deutlich
    • Innerhalb eines Jahres stieg die Zahl der Verbesserungen an Shared Libraries von 32 auf 46
    • Ein einzelner Engineer kann ein Deployment innerhalb weniger Minuten durchführen
  • Auch die operative Effizienz verbesserte sich, da Lastspitzen durch große Worker-Pools aufgefangen werden können
  • Es gibt jedoch auch Nachteile, darunter schwierigere Fehlerisolation, geringere Cache-Effizienz und Risiken bei Dependency-Updates
    • Ein Teil dieser Nachteile wird durch einfacheren Betrieb und höhere Produktivität ausgeglichen

Fazit

  • Microservices lösten anfangs Leistungsprobleme, sind aber für großflächige Skalierung und gebündelte Updates weniger geeignet
  • Durch die Umstellung auf einen Monolithen wurden Betriebsstabilität und Entwicklungsgeschwindigkeit gleichermaßen verbessert
  • Für eine erfolgreiche Umstellung sind ein robustes Testsystem und die Akzeptanz von Trade-offs entscheidend
  • Twilio Segment setzt zwar in Teilen seiner Infrastruktur weiterhin auf Microservices, bewertet jedoch für serverseitige Destinations einen Monolithen als die geeignetere Struktur

2 Kommentare

 
yangeok 2025-12-16

Es scheint riskant zu sein, alles bis ins kleinste Detail aufzuteilen und zu normalisieren.

 
GN⁺ 2025-12-14
Hacker-News-Kommentare
  • Als man den Code für alle Ziele in einem einzigen Repo zusammenführte, konnte man ihn zu einem einzelnen Service verschmelzen.
    Das Ergebnis war eine deutlich höhere Entwicklungsgeschwindigkeit. Jetzt müssen nicht mehr über 140 Services deployt werden, nur weil eine gemeinsame Bibliothek geändert wurde.
    Ein einzelner Engineer kann nun innerhalb weniger Minuten deployen.
    Wenn wegen einer Bibliotheksänderung alle Services neu deployt werden müssen, dann ist das kein echter Service, sondern ein verteilter Monolith.
    Schon die Vorstellung, gemeinsame Bibliotheken zwanghaft über alle Services hinweg zu synchronisieren, passt nicht zur Philosophie einer Service-Architektur.

    • Da ist etwas dran, aber in der Praxis ist die Lage deutlich komplexer.
      Das ist weniger „bei jedem Bibliotheks-Update alles neu deployen“ als vielmehr ein Amazon-artiges gemeinsames Build- und Deployment-System.
      Bibliotheken werden aus einer zentral verwalteten Quelle bezogen, und bei Versionsunterschieden müssen wegen Kompatibilitätsproblemen alle migriert werden.
      Wenn wegen einer Sicherheitslücke eine bestimmte Version entfernt werden muss, ist ein kompletter Redeploy nötig, aber die Vorteile der zentralisierten Verwaltung sind viel größer.
      Solche Systeme werden weiterhin als Mikroservices eingeordnet, verhalten sich aber in Bezug auf Kosten und operative Effizienz wie eine gemeinsame Umgebung.
      Das als verteilten Monolithen zu bezeichnen, ist eine Überinterpretation.
    • Das klingt einfach, führt in der Praxis aber leicht zu subtilen Bugs oder Inkompatibilitäten zwischen Services.
      Wenn man dem Mikroservice-Muster folgt, steigt das Deployment-Risiko, auch wenn man das anfangs nicht bemerkt.
      Wenn man zum Beispiel einen Bug in einer Geld-Bibliothek behoben hat, steht man realistisch vor der Frage, ob nun alle Services neu deployt werden müssen.
    • Dass Bibliotheken systemweit aktualisiert werden müssen, bedeutet nicht automatisch falsche Kopplung.
      Eine Bibliothek mit Sicherheitslücken muss unabhängig vom Systemdesign ohnehin überall ersetzt werden.
      In solchen Fällen ist eine monolithische Struktur sogar leichter zu handhaben.
    • Schon das Konzept gemeinsamer Bibliotheken koppelt alle Services eng aneinander.
      Echte Mikroservices sollten Nachrichten austauschen und JSON verwenden.
      Man sollte nur die API kennen müssen, nicht den Code. Nur dann kann unabhängig deployt und skaliert werden.
    • Heißt das dann, dass man in jedem der 140 Services den Logging-Code neu schreiben soll?
      Ist es nicht sinnvoller, gemeinsame Module zu verwenden?
  • In meiner vorherigen Firma lief alles als Mikroservices, die Firma davor setzte auf AWS Serverless.
    In beiden Fällen war die Kommunikation zwischen den Services das größte Problem. Contracts ließen sich schwer synchronisieren, und auch Deployments waren kompliziert.
    Anfangs ging es schnell voran, aber mit der Zeit explodierte die Komplexität. Es entstand fear-based development, und es gab viel zu viele Meetings.
    Meine jetzige Firma hat eine monolithische Struktur, und sie ist viel einfacher zu handhaben. Typen sind klar, Refactorings einfach.
    Es ist spannend zu sehen, wie auf unserer eigenen Plattform aufgebaute AI-Agenten sich innerhalb der Codebasis selbst verbessern.
    Der einzige Nachteil sind längere Build-Zeiten, aber durch Fortschritte in der Toolchain erwarte ich bis 2026 10-mal schnellere Deployments.
    Mein Fazit ist, dass wir dank der monolithischen Struktur deutlich schneller wachsen und skalieren konnten.

    • Meine Erfahrung ist genau umgekehrt. Ich habe 10 Jahre bei SendGrid gearbeitet und miterlebt, wie wir von 12 auf 500 Leute gewachsen sind, und das war dank einer Service-Architektur möglich.
      In monolithischen Strukturen wurde die Trennung von Zuständigkeiten ständig verletzt, und die Kopplung zwischen Teams war stark.
      Echte Geschwindigkeit und Skalierung waren nur möglich, wenn die Teams voneinander getrennt waren.
      Der Wechsel von ORM zu DTO hat 2 Jahre, 50 Teams und mehr als 150 Personen gebraucht.
      Eine so komplexe Arbeit wäre ohne Mikroservices nicht möglich gewesen.
  • Beim Lesen dieses Artikels wirkt es so, als liege das Kernproblem nicht in der technischen Wahl Mikroservices vs. Monolith, sondern in der Qualität und Struktur der Engineering-Organisation.
    Code-Repository und Teststruktur zeigen das Niveau der Organisation direkt.

    • Vielen Teams fehlt technische Disziplin.
      Wenn niemand sagen kann „Das machen wir nicht“, explodiert die Komplexität.
      Es braucht eine Führungsperson mit Autorität, damit das Team innehält und nachdenkt.
    • Ich habe an einem Twilio-Projekt mitgearbeitet, und es war wirklich chaotisch.
      Wenn es API-Probleme gab, wurde die Ursache nicht analysiert, sondern nur die Daten angepasst und das Ticket geschlossen.
      Selbst wenn dasselbe Problem wiederkam, wurde die eigentliche Ursache nicht behoben.
    • Conways Gesetz wird wieder einmal bestätigt.
      Schon im Interview kann man den Aufbau der Codebasis eines Unternehmens bis zu einem gewissen Grad vorhersagen.
  • Das ist weniger eine echte Rückkehr zum Monolithen als weiterhin eine SOA-Struktur.
    Nur der Umfang der Services ist größer geworden.
    Wenn ein Team 140 Services verwaltet, dann dient SOA der Skalierung des Teams, nicht der Skalierung der Services.
    Wenn ein einzelnes Team alle gemeinsamen Bibliotheken verwaltet, entstehen Versionskonflikte und API-Verwirrung.
    Am Ende bestimmt die Organisationsstruktur die Architektur. Ein Team hat integriert, um die Komplexität zu senken.
    Das ist kein „Monolith“, sondern ein auf Team-Ebene passend zugeschnittener Service-Level.
    Ich halte so eine Struktur für ideal. Wenn das Team größer wird, muss man wieder aufteilen.

  • Ich bin kein Mikroservice-Verfechter, aber die falsche Dichotomie Monorepo vs. Mikroservices fällt mir auf.
    Zu viele Tools setzen stillschweigend ein 1:1-Verhältnis zwischen Service und Repo voraus.
    Man kann aber trotzdem alles in einem Repo haben und unabhängig deployen.
    Es wäre schön, wenn man bei GitHub oder ähnlichen Plattformen Ordner als eigenständige Services behandeln könnte.

    • Das habe ich in einer früheren Firma selbst umgesetzt.
      Mit Bazel wurde der Abhängigkeitsbaum verwaltet, und über bazel query wurden betroffene Targets gefunden, um Tests automatisch auszuführen.
      Zusammen mit GitHub Actions haben wir einen Workflow gebaut, der PRs blockiert.
      Das funktionierte gut, aber der Aufbau hat mehrere Monate gedauert.
    • Die Aussage „Wir sind von Mikroservices zum Monolithen gewechselt und die Probleme waren weg“ stört mich.
      Das eigentliche Problem war mangelnder Betrieb und fehlende Tooling-Unterstützung — CI, Autoscaling und On-Call-Strukturen waren alle unzureichend.
  • Beide Ansätze können scheitern.
    In Umgebungen wie Node.js oder Python gibt es Grenzen dafür, wie viel Code die Event Loop verarbeiten kann.
    Ich habe schon erlebt, dass 6–8 Personen 200 Services verwaltet haben, und auch, dass 80 Personen einen einzigen Monolithen betreut haben.
    Mikroservices sind bei kleinen Änderungen im Vorteil, aber bei systemweiten Änderungen schwierig,
    monolithische Strukturen genau umgekehrt.
    Am Ende sind nicht die Architektur, sondern Abstraktion, Tests und die Art der Entkopplung entscheidend.

    • „Wenn Software ein einziges Business-Problem löst, sollte sie in einem einzigen Mikroservice gebündelt sein.“
      Der Maßstab für „micro“ ist nicht die Technik, sondern die Business-Einheit.
      Wenn man noch kleiner schneidet, werden daraus Nanoservices.
    • Diese Rationalisierung wirkt am Ende wie ein Provisorium, das nur Laufzeitgrenzen verdeckt.
      In Umgebungen wie Beam, JVM, Rust oder Go ist das längst gelöst.
    • Mich würde interessieren, in welcher konkreten Einheit sich diese Grenze der von der Event Loop verarbeitbaren Code-Menge ausdrückt.
      Geht es um CPU-Cache-Probleme?
    • Ich frage mich, ob in großen Umgebungen wirklich Node.js oder Python verwendet wird.
      Ich dachte, dort nehme man eher Go, Java oder C#.
  • In den meisten Firmen waren Mikroservices eher die Ursache von 90 % der Probleme.
    Wenn man keine riesige Organisation wie AWS, Google oder Netflix ist, passt das meist nicht.
    Es ist schon schwer genug, ein System in sinnvoll kombinierbare Einheiten zu zerlegen; zusätzlich noch Netzwerkgrenzen einzuziehen, ist töricht.
    Der nächste Trend wird sich wohl von React und SPAs weg und hin zu einer serverzentrierten Ausrichtung bewegen.

  • Dass man auf Mikroservices umgestiegen ist, „weil Tests oft kaputtgingen“, wirkt wie ein völlig verkehrter Ansatz.
    Weil Tests fehlschlagen, die gesamte Struktur der Codebasis umzubauen, ist seltsam.

    • Wir hatten ein ähnliches Problem, haben es aber gelöst, indem wir jedem Team eigene Entwicklungsumgebungen gegeben haben.
      Durch getrennte VMs und CI/CD-Konfigurationen pro Team verschwanden die Testkonflikte.
      Der Nachteil ist, dass Konflikte zwischen Features nicht sofort sichtbar werden, aber durch klare Code-Zuständigkeiten war das kein großes Problem.
  • Es gab die Bitte, dem Titel [2018] hinzuzufügen.

    • Ich frage mich, ob man inzwischen vielleicht wieder zu Mikroservices zurückgekehrt ist.
    • Einen sieben Jahre alten Artikel wieder hervorzuholen, finde ich etwas fragwürdig. In der Tech-Welt ist das schon uralte Geschichte.
  • Es heißt, man habe das Repo getrennt, weil „bei kaputten Tests auch nicht verwandter Code geändert werden musste“,
    aber es hätte wohl auch andere Lösungen gegeben, etwa die Art der Testausführung zu ändern oder manuelle Deployments zuzulassen.
    Die Trennung des Repos war nicht die einzige mögliche Lösung.