LLMs zu betreiben wird oft als Kapazitätsproblem beschrieben: mehr Replicas hinzufügen, Queues beobachten, GPUs auslasten. Diese Sicht übersieht einen wichtigen Punkt vieler realer Workloads. Zwei Anfragen können vom selben Modell unterschiedliche Antworten verlangen und dennoch große Teile bereits verarbeiteten Context teilen: einen System Prompt, einen Repository-Snapshot, eine Conversation History oder den stabilen vorderen Teil eines RAG-Prompts.

Das Modell muss diesen Context verarbeiten, bevor es den ersten neuen Token erzeugen kann. Hat ein Worker diese Arbeit bereits erledigt, kann es eine teure Form von Fairness sein, die nächste ähnliche Anfrage an einen anderen freien Worker zu schicken. Der neue Worker beginnt bei null; der erste hält nützlichen Zustand, erhält aber keine Arbeit.

Genau um diesen Zielkonflikt geht es bei Cache-aware Scheduling. Damit ist die Platzierung von LLM-Anfragen gemeint, bei der wiederverwendbarer Ausführungszustand neben üblichen Signalen wie Queue-Tiefe, verfügbarer Kapazität und Latenzzielen berücksichtigt wird. In heutigen LLM-Systemen ist der wichtigste wiederverwendbare Zustand meist der KV cache: gespeicherte Attention-Daten von Tokens, die das Modell bereits verarbeitet hat.

Einfach gesagt: Eine freie GPU ist nicht automatisch die schnellste GPU für eine Anfrage. Am schnellsten kann die GPU sein, die den größten Teil ihres Context bereits gelesen hat.

Das Routing-Problem hinter Prefix Caching

Ein Transformer liest einen Prompt nicht im alltäglichen Sinn erneut, berechnet jedoch für jeden Input-Token interne Key- und Value-Repräsentationen, während er den für Attention genutzten Context aufbaut. Ein KV cache bewahrt diese Repräsentationen auf. Hat eine spätere Anfrage denselben kompatiblen Anfang, kann das Serving-System die gespeicherte Arbeit wiederverwenden und nur den nicht übereinstimmenden Rest berechnen.

Das ist Prefix caching: die Speicherung und Wiederverwendung von Berechnungen für einen gemeinsamen Token-Präfix. Es kann die Prefill-Arbeit reduzieren – die Phase, in der das Modell den Input-Context verarbeitet, bevor die Generierung beginnt. Gerade bei langen Prompts trägt Prefill häufig erheblich zur Zeit bis zum ersten Token bei.

Ein Cache ist aber nur dort nützlich, wo er verfügbar ist. In einem Service mit Replicas kann jeder Worker andere Cache-Inhalte halten. Ein Cache-blinder Load Balancer kann Anfragen gleichmäßig verteilen und dennoch jede Replica denselben großen Präfix erneut berechnen lassen. Cache-aware Scheduling ergänzt vor dem Dispatch eine Frage: Welcher Worker oder welcher Cache-Tier hält mit der größten Wahrscheinlichkeit bereits kompatiblen Zustand?

Eine aktuelle SageMaker-Funktion von Amazon macht diese Idee greifbar. Das Prefix-aware Routing sendet Anfragen mit gemeinsamem Präfix an dieselbe Inference Instance und stellt Einstellungen für Präfixlänge und einen Concurrency-Schwellenwert bereit. Die API-Dokumentation beschreibt diese Routing-Einstellungen. AWS berichtet in seinem konkreten Benchmark von bis zu 77 % niedrigerer P50-Zeit bis zum ersten Token sowie höheren KV-cache-Hit-Raten. Das ist ein Ergebnis des Anbieters für diesen Workload und diese Konfiguration, keine allgemeingültige Einsparung. Details und Einordnung des Benchmarks stammen von AWS.

Warum ist das jetzt wichtig? LLM-Anwendungen bauen zunehmend auf bewusst stabilem Context auf. Ein Coding Assistant kann Repository-Anweisungen und Tool-Definitionen voranstellen. Ein Support-Agent führt Conversation History und Policy Prompt über mehrere Turns weiter. Eine RAG-Anwendung kann Tenant-spezifische Anweisungen, Retrieval-Policy und wiederkehrendes Quellmaterial vor die Frage des Nutzers setzen. Mit wachsendem Context wird Platzierung zu einer Entscheidung der Serving-Architektur statt zu einer kleinen Einstellung des Load Balancers.

Wie die Entscheidung funktioniert

Die genaue Implementierung unterscheidet sich, und die Begriffe sind nicht vollständig standardisiert. „Prefix-aware routing“ meint häufig die Auswahl einer Replica anhand eines gemeinsamen Präfixes. „Cache-aware“ ist weiter gefasst: Es kann Routing zwischen Replicas, die Wahl zwischen GPU-, CPU- oder Storage-Tiers, Cache-Migration und die Koordination getrennter Prefill- und Generation-Worker umfassen.

Ein hilfreiches Modell besteht aus fünf Schritten.

Zuerst bestimmt das System eine Cache-relevante Identität der eingehenden Anfrage. Sie kann aus tokenisierten Prompt-Präfixen oder aus Metadaten abgeleitet werden, die einen passenden Präfix vorhersagen. Token-Gleichheit allein reicht nicht zwingend: Modellversion, Tokenizer-Konfiguration, Adapter, versteckte System-Inputs und Authorization Context können beeinflussen, ob Wiederverwendung korrekt ist.

Zweitens schätzt die Control Plane die Cache-Residenz. Sie muss wissen, welcher Worker passende Blöcke hat, wie viel des Präfixes übereinstimmt und ob diese Blöcke wahrscheinlich noch verfügbar bleiben. Implementierungen können Cache-Einträge in Blöcken oder in einer Präfix-orientierten Struktur wie einem Radix Tree organisieren. Der zentrale Architekturpunkt ist nicht die Datenstruktur, sondern dass der Ort des Caches zum Eingabesignal für die Planung wird.

Drittens bewertet der Scheduler die Kandidaten. Ein längerer wiederverwendbarer Präfix kann mehr Prefill-Berechnung vermeiden, doch ein Worker mit dem besten Match kann zugleich eine tiefe Queue haben. Die Policy gewichtet daher erwartete Wiederverwendung gegen Queueing, Kapazität und ein Latenzziel. Jede passende Anfrage an eine Replica zu senden, kann aus einem warmen Cache einen Hotspot machen.

Einfach gesagt: Der Scheduler wägt ab: alte Arbeit auf einer beschäftigten Maschine wiederverwenden oder sie auf einer weniger beschäftigten Maschine erneut ausführen.

Viertens sucht der ausgewählte Worker passende KV-Blöcke und verwendet sie wieder; anschließend verarbeitet er den abweichenden Suffix. Ein Cache Hit macht eine Anfrage nicht kostenlos. Das Modell muss neue Tokens weiterhin verarbeiten und eine Antwort generieren; bei langen Ausgaben kann die Generierung die Gesamtdauer dominieren, selbst wenn Prefill günstig ist.

Zuletzt behält, verwirft oder verschiebt das System Zustand gemäß Speicherdruck und erwartetem künftigen Wert. Die Lebensdauer des Caches gehört zur Scheduling-Policy. Eine Route, die auf einer gestrigen Cache-Map beruht, scheitert, wenn ein Worker neu gestartet wurde, eine lange Generierung relevante Blöcke verdrängt hat oder ein Cache-Index veraltet ist.

Dieselbe Logik wird mit Disaggregated serving komplizierter. Diese Architektur trennt Prefill von Decode – der Token-für-Token-Generierungsphase – häufig in unterschiedliche Worker-Pools. Cache-aware Placement kann einen Prefill-Worker mit passendem Zustand wählen und diesen Zustand anschließend für einen Decode-Worker verfügbar machen. Das kann die Auslastung verbessern, aber das Übertragen oder Bereitstellen des Zustands verursacht Kosten und Koordinationsaufwand. Disaggregated serving ist nicht dasselbe wie Cache-aware Scheduling; es ist eine Architektur, in der Cache-aware Scheduling mehr Ansatzpunkte hat.

Was es nicht ist

Cache-aware Scheduling ist nicht einfach gewöhnliches Load Balancing mit einem neuen Namen. Round-Robin-, Least-Connections- und auslastungsbasierte Policies beantworten die Frage „Wo gibt es Kapazität?“. Cache-aware Policies fragen zusätzlich: „Wo liegt bereits berechnete Arbeit?“ Keine der beiden Fragen sollte automatisch gewinnen.

Es ist auch nicht Prefix caching selbst. Prefix caching ist der Mechanismus, der Zustand speichert und wiederverwendet. Ein Server mit nur einem Worker kann sehr gutes Prefix caching haben, ohne überhaupt Routing entscheiden zu müssen. Umgekehrt kann ein Router Session Affinity erhalten, ohne zu wissen, ob ein kompatibler Cache-Eintrag überlebt hat. Das Gesamtsystem braucht sowohl Wiederverwendung als auch informierte Platzierung.

Ebenso wenig ist es Model routing. Model routing wählt ein Modell anhand von Fähigkeit, Kosten oder Qualität. Cache-aware Scheduling setzt üblicherweise nach dieser Wahl an: Es platziert Arbeit für das bereits gewählte Modell. Beide Entscheidungen zusammenzuführen kann sinnvoll sein, aber sie optimieren unterschiedliche Dinge.

Und es erlaubt nicht, gleiche Tokens als gleichen Sicherheitskontext zu behandeln. Ein Cache namespace trennt Cache-Einträge, die nicht geteilt werden dürfen. Ein Service mit mehreren Tenants oder Berechtigungsstufen braucht Identitäts- oder Salting-Regeln, die relevanten Tenant- und Authorization Context einbeziehen. Sonst kann ein oberflächlich identischer Präfix zu unsicherer Wiederverwendung oder falscher Semantik führen.

Beispiel: ein Repository Assistant unter realem Traffic

Betrachte einen hypothetischen internen Coding Assistant. Jede Anfrage enthält einen stabilen System Prompt, Tool-Definitionen, Organisationsrichtlinien und eine kompakte Repository Map. Danach folgen die Frage des Nutzers und ausgewählte Dateien. Mehrere Engineers können innerhalb kurzer Zeit Fragen zum selben Repository stellen.

Bei Cache-blindem Balancing landet Anfrage eins auf Replica A und baut den Präfixzustand auf. Anfrage zwei mit nahezu gleichem Context landet auf Replica B, weil B weniger ausgelastet ist. B wiederholt das aufwendige Prefill. Bei einer Cache-aware Policy erkennt der Router den kompatiblen Präfix und vergleicht die erwartete Wiederverwendung auf A mit der Queue-Strafe von A. Ist A nur etwas stärker beschäftigt, sendet die Policy Anfrage zwei an A. Ist A ausgelastet, kann sie die Anfrage an B senden, statt Locality auf Kosten einer unakzeptablen Wartezeit zu schützen.

Die Präfixidentität muss strenger sein als „dasselbe Repository“. Ein anderes Model Release, eine andere Repository-Revision, Policy-Version, ein Adapter oder ein anderer Access Scope kann Wiederverwendung ungültig machen. Der Service sollte seinen Cache entsprechend partitionieren. Außerdem sollte er das Ergebnis auf Anfrageebene messen: Präfixlänge, geschätzte und tatsächliche wiederverwendete Tokens, Cache-Hit-Rate, Queue-Zeit, Zeit bis zum ersten Token, End-to-End-Latenz, Eviction-Rate und den ausgewählten Worker.

Diese Messungen sind nützlicher als eine einzige aggregierte Hit-Rate. Eine hohe Hit-Rate kann mit schlechterer Tail-Latenz einhergehen, wenn eine warme Replica zu viel Traffic erhält. Ebenso kann eine niedrigere durchschnittliche Prefill-Zeit unwichtig sein, wenn lange Generierung die Anwendung dominiert. Der Service braucht ein SLO – ein festgelegtes Zuverlässigkeits- oder Latenzziel – und sollte die Policy mit repräsentativem Traffic statt mit einer sauberen Folge identischer Prompts bewerten.

Wo es scheitert

Der erste Fehlerfall ist geringe Wiederverwendung. Stark variable Prompts, kurze gemeinsame Präfixe und Einträge, die vor dem Eintreffen einer verwandten Anfrage verworfen werden, lassen wenig Arbeit einsparen. Ein Burst identischer Anfragen kann zudem eintreffen, bevor die erste Anfrage den Cache vollständig gefüllt hat.

Der zweite ist Ungleichgewicht. Locality konzentriert Arbeit. Sie kann Cache-tragende Replicas überlasten, während kalte Replicas unausgelastet bleiben. Workloads mit beliebten Dokumenten, gemeinsamen Agent-Anweisungen oder wenigen aktiven Repositories sind besonders anfällig. Cache-aware Routing braucht deshalb explizite Queue- oder Concurrency-Limits, Fallbacks und die Bereitschaft, bei zu hohen Latenzkosten auf einen Hit zu verzichten. Zusätzliche Vorverarbeitung und Cache-Tracking sowie Zielkonflikte durch ungleichmäßige Last sind dokumentierte Aspekte Cache-aware Designs. NVIDIA beschreibt die Tracking- und Platzierungsabwägungen; BanaServe untersucht das Ausbalancieren von Cache-Zustand in Disaggregated Serving. Das BanaServe-Paper ist eine eigenständige Forschungsquelle.

Der dritte Fehlerfall betrifft die Korrektheit der Control Plane. Ein veralteter Blick auf Cache-Residenz, Worker-Churn, unterschiedliche Cache-Versionen oder ein falscher Kompatibilitätsschlüssel können eine Optimierung unbemerkt in eine Latenzregression oder ein Korrektheitsproblem verwandeln. Behandle Cache-Metadaten als verteilten Zustand: Lege fest, was nach einem Neustart geschieht, wie Einträge invalidiert werden und welche Komponente maßgeblich ist.

Was du als Senior Engineer tun kannst

Beginne damit, stabile Präfixe in Production Traces zu finden. Leite das Wiederverwendungspotenzial nicht allein aus Prompt Templates ab; miss die Token-basierte Gemeinsamkeit tatsächlicher Anfragen, das Ankunftstiming und Cache-Lebensdauern. Trenne nach Workload: interaktiver Chat, RAG, Coding und Batch-Verarbeitung können sich sehr unterschiedlich verhalten.

Erstelle dann eine Cache-aware Baseline. Vergleiche bei einem repräsentativen Traffic Replay Cache-blinde Platzierung mit einer Affinity-Policy, die eine Load Penalty enthält. Erfasse P50 und Tail-Zeit bis zum ersten Token, End-to-End-Latenz, Queue-Zeit, Cache Hits, Schätzungen wiederverwendeter Tokens, Eviction und Auslastung pro Replica. Halte Modell, Hardware, Traffic-Form und SLO beim Vergleich konstant.

Mache Kompatibilität und Isolation explizit. Versioniere die Cache-Identität bei Änderungen an Modell und Tokenizer; beziehe Adapter und relevante Versionen versteckten Contexts ein; partitioniere nach Tenant und Authorization Scope. Teste negative Fälle absichtlich: Zwei ähnlich aussehende Prompts, die keinen Zustand teilen dürfen, dürfen nie demselben wiederverwendbaren Eintrag zugeordnet werden.

Instrumentiere schließlich die Entscheidung, nicht nur das Ergebnis. Die GenAI Semantic Conventions von OpenTelemetry definieren Felder und Operationsnamen für Agents, Conversations, Workflows, Provider, Tools, Retrieval und die Nutzung gecachter Tokens. Die Spezifikation warnt außerdem, dass Tool-Call-Argumente und Ergebnisse sensible Daten enthalten können. Das praktische Ziel ist überschaubar: Wenn sich die Latenz verändert, solltest du erkennen können, ob ein verpasster Präfix, eine Eviction, eine Queueing-Entscheidung, ein Transfer oder die Generierungsarbeit des Modells die Ursache war.

Cache-aware Scheduling macht Context nicht kostenlos. Es macht eine bisher versteckte Ressource sichtbar – den Ort bereits berechneten Contexts – für das System, das über die Platzierung von Arbeit entscheidet. Für Serving-Teams ist das die entscheidende Veränderung: Behandle Routing und Caching nicht als getrennte Optimierungen, sondern bewerte sie als eine Policy mit Folgen für Latenz, Kapazität, Fairness, Korrektheit und Isolation.