Vor fünf Jahren präsentierte ich einem Kunden stolz ein detailliertes Latenz-Budget für ein neues System. Jede Komponente war analysiert: Der Auth-Service sollte 15 Millisekunden benötigen, die Geschäftslogik 30 ms und die Datenbankabfrage 40 ms. Die Summe lag weit unter der angestrebten 200-ms-Marke. Doch schon in der ersten Produktionsphase brach das System regelmäßig zusammen – nicht wegen eines Codefehlers, sondern wegen einer grundlegenden Architekturentscheidung, die niemand bedacht hatte.
Wenn Messungen die falschen Fragen stellen
Der Glaube, Latenz ließe sich durch späte Optimierung beheben, ist weit verbreitet. Entwickler testen Komponenten isoliert, messen Durchsatz und beheben offensichtliche Engpässe wie langsame Datenbankabfragen oder ineffiziente Schleifen. Doch diese Herangehensweise übersieht, dass Latenz oft schon in der Systemstruktur angelegt ist – lange bevor der erste Nutzer die Anwendung nutzt.
Ein klassisches Beispiel ist die synchrone Abhängigkeit von asynchronen Prozessen. Wenn eine API-Anfrage darauf wartet, dass eine Hintergrundverarbeitung abgeschlossen ist, bevor sie eine Antwort zurückgibt, wird die Latenz automatisch auf die Dauer des langsameren Prozesses begrenzt. Kein Caching, kein Connection Pooling und keine Datenbankindex-Optimierung können diesen Wert unterschreiten. Die Lösung liegt nicht in der Feinjustierung, sondern in der Neugestaltung der Schnittstellen zwischen synchronen und asynchronen Abläufen.
Ein weiteres oft unterschätztes Problem ist die unbegrenzte Ausbreitung von Anfragen. Ein Nutzer könnte beispielsweise eine Filterfunktion mit einer Abfrageparameterlänge aufrufen, die in der Entwicklung nie getestet wurde. Während ein Standardnutzer in 20 ms eine Antwort erhält, dauert dieselbe Abfrage für einen Power-User plötzlich drei Minuten – und dieser Nutzer ist oft der wirtschaftlich wertvollste Kunde. Späte Anpassungen wie Paginierung oder Query-Limits werden dann zu politischen Diskussionen, statt zu technischen Lösungen.
Warum Lasttests die Realität verfehlen
Lasttests simulieren typische Nutzungsszenarien, doch die Produktion bringt unvorhergesehene Muster mit sich. Shared Dependencies – gemeinsam genutzte Ressourcen wie Datenbanken oder Auth-Services – führen zu unerwarteten Spitzenlasten, wenn mehrere Dienste gleichzeitig auf dieselbe Infrastruktur zugreifen. Im genannten Fall teilte sich der Auth-Service vier weitere Dienste, die alle zur gleichen Stoßzeit aktiv waren. Die ursprüngliche Annahme von 15 ms pro Aufruf war damit obsolet, ohne dass dies im Vorfeld aufgefallen wäre.
Die Illusion, man könne Latenz nachträglich optimieren, entsteht oft durch eine falsche Priorisierung. Entwickler konzentrieren sich auf offensichtliche Codepfade, während strukturelle Entscheidungen wie Microservice-Granularität oder Datenflussdesign unangetastet bleiben. Doch diese Entscheidungen definieren die minimale erreichbare Latenz – unabhängig von späteren Code-Optimierungen.
Latenz-Budgets: Die Kunst der Voraussicht
Der Schlüssel liegt darin, Latenz nicht als Messgröße, sondern als Designentscheidung zu behandeln. Bevor der erste Codezeile geschrieben wird, sollte das Team ein Latenz-Budget für jeden kritischen Pfad definieren. Dieses Budget muss nicht nur technisch machbar, sondern auch realistisch unter Last sein.
Ein praktisches Vorgehen:
- Zielvorgabe festlegen: Was ist die maximale akzeptable Antwortzeit für den Nutzer?
- Kritische Pfade identifizieren: Welche Komponenten müssen diese Zeit einhalten?
- Puffer einplanen: Erfahrungen zeigen, dass mindestens 20–30 % Reserve für unerwartete Lastspitzen eingeplant werden sollten.
- Shared Dependencies prüfen: Werden Ressourcen von mehreren Diensten genutzt? Wenn ja, wie wirken sich Lastspitzen aus?
- Trade-offs dokumentieren: Welche Kompromisse sind akzeptabel, um die Latenz zu halten? Müssen Daten denormalisiert werden? Können Berechnungen asynchron erfolgen?
Das Aufschreiben dieser Budget-Regeln zwingt das Team, architektonische Entscheidungen frühzeitig zu diskutieren – nicht erst während eines nächtlichen Vorfalls. Ein dokumentiertes Budget macht sichtbar, welche Kompromisse bewusst eingegangen wurden und welche Konsequenzen daraus resultieren.
Der wirtschaftliche Preis hoher Latenz
Die Auswirkungen von vermeidbarer Latenz gehen über technische Probleme hinaus. Bei einer Last von 100.000 Anfragen pro Sekunde summieren sich bereits 10 Millisekunden zusätzliche Latenz pro Nutzer auf 1.000 Sekunden verlorene Wartezeit pro Sekunde Systemlaufzeit. Das entspricht einer Stunde Nutzerzeit, die jede Sekunde ungenutzt verstreicht. Für E-Commerce-Plattformen oder Finanzanwendungen kann dies direkt zu Umsatzverlusten führen.
Teams, die diese Zahlen kennen, priorisieren Latenz nicht als technischen Luxus, sondern als Kundenerlebnis-Faktor. Sie investieren frühzeitig in Architektur-Entscheidungen, die spätere Überraschungen vermeiden – statt wertvolle Ressourcen in nachträgliche Optimierungen zu stecken, die oft nur Symptome behandeln, nicht die Ursache.
In der nächsten Folge dieser Reihe gehen wir der Frage nach, wie Teams solche Budget-Entscheidungen in agilen Umgebungen umsetzen können, ohne die Flexibilität der Entwicklung einzuschränken. Denn gute Architektur ist keine starre Vorgabe, sondern ein dynamischer Prozess – der jedoch klare Leitplanken braucht, bevor der Code geschrieben wird.
KI-Zusammenfassung
Sistemlerinizin gecikme bütçesini inşa etmeden belirleyin. Ölçeklenmeyi engelleyen gizli mimari tuzakları keşfedin ve kullanıcı deneyiminizi koruyun.