Provider Drift: Wie Standard-Routing die LLM-Kosten in die Höhe treibt
Inhalt
Sie haben Prompt-Caching aktiviert, der Treffer-Zähler tickt ab und zu, aber Ihre Rechnung hat sich kaum verändert. Bevor Sie Ihre Prompt-Struktur beschuldigen, schauen Sie sich etwas an, das das Dashboard verbirgt: welcher Upstream tatsächlich jede Anfrage bedient hat.
Multi-Provider-Gateways verteilen ein einzelnes Modell auf mehrere Upstream-Provider und wählen pro Anfrage einen aus. Prompt-Caches sind pro Provider (oft pro Knoten innerhalb eines Providers). Wenn Ihre zweite identische Anfrage also auf einem anderen Upstream landet als die erste, ist das ein Cache-Miss, obwohl sich Ihr Prompt um kein einziges Byte verändert hat. Das ist Provider Drift, und bei einem Pay-per-Token-Modell vervielfacht es Ihre Kosten leise.
Die zwei Bedingungen, die es auslösen
Das ist keine Fehlkonfiguration, für die Sie sich entschieden haben. Es ist das, was Sie standardmäßig erhalten:
- Standard-Auto-Routing. Die Anfrage wird an das Modell gesendet, ohne einen Upstream festzulegen, sodass das Gateway pro Aufruf einen auswählt.
- Standard-Provider-Sortierung = „default (balanced)”. Das Gateway verteilt die Last über alle infrage kommenden Upstreams, anstatt bei einem zu bleiben.
Beides sind die Werkseinstellungen. Sie müssen nichts anfassen, um Drift zu bekommen; Sie müssen Einstellungen anfassen, um ihn zu vermeiden.
Wie 20 identische Anfragen aussehen
Wir haben das gleiche Präfix von ~8K Token 20 Mal hintereinander an ein beliebtes Multi-Provider-Gateway gesendet, mit den oben genannten Standardeinstellungen, und jedes Mal nach den vom Upstream selbst gemeldeten Provider- und Cache-Feldern gefragt. Für ein Disk-Cache-Modell aus der DeepSeek-Familie:
- 9 verschiedene Upstreams bedienten die 20 Aufrufe:
N***a,S***w,M***h,D***a,A***L,P***l,S***e,V***e,A***d. - Cache-Trefferquote: 4/20 (20 %). Sie treffen nur bei den Aufrufen, die zufällig auf einem Upstream landen, der Ihr Präfix bereits zwischengespeichert hatte.
Führen Sie dieselben 20 Aufrufe gegen ein Single-Backend-Gateway aus (ein Modell, ein Upstream, kein Balancing), und die Trefferquote liegt bei 19/20 (95 %) für dieselbe Arbeitslast. Gleiches Modell, gleicher Prompt, gleiche Anzahl von Aufrufen. Die einzige Variable ist, ob das Routing driftet.
Zum Kontrast: Auf genau demselben Multi-Provider-Gateway wurde ein GPT-Klasse-Modell für alle 20 Aufrufe an einen Upstream (A***e) geroutet und traf 19/20. Drift ist nicht einheitlich; er trifft jeweils das Modell, das das Gateway zufällig verteilt, und bei diesem Durchlauf war das das Modell der DeepSeek-Familie.
Schlussfolgerung A: die erwarteten Kosten vs. die bezahlten Kosten
Die Kosten pro Aufruf beim driftenden Modell teilten sich sauber nach dem Cache-Ergebnis auf:
| Aufruftyp | Median-Kosten / Aufruf |
|---|---|
| Cache-Treffer | ~$0.00015 |
| Cache-Miss | ~$0.00062 |
Ein Miss kostet bei diesem Modell etwa 4x so viel wie ein Treffer (bei den reinen Input-Token ist die veröffentlichte Lücke noch größer, etwa 50x). Nun rechnen wir das über die 20 Aufrufe zusammen:
| Szenario | Trefferquote | Kosten für 20 identische Aufrufe |
|---|---|---|
| erwartet (Cache erreichbar) | 95 % | $0.0026 |
| tatsächlich (Standard-Drift) | 20 % | $0.0102 |
Gleiches Modell, gleicher Prompt, gleiche 20 Anfragen. Provider Drift machte den Durchlauf ~3,9x teurer. Das Caching war die ganze Zeit „eingeschaltet”; die Routing-Schicht hat einfach die meisten Ihrer Token zum Miss-Tarif berechnet. Skalieren Sie das auf einen Produktions-Endpunkt, der den ganzen Tag ein großes stabiles Präfix abspielt, und die Lücke macht den Großteil Ihrer Input-Ausgaben aus.
Schlussfolgerung B: kein Cache bedeutet auch kein Latenz-Gewinn
Caching ist nicht nur ein Kostenhebel. Ein warmer Prefill liefert den ersten Token früher. Wenn Drift Ihnen den Cache verwehrt, verlieren Sie auch diese Beschleunigung. Wir haben die Time-to-First-Token (TTFT) bei wiederholten identischen Aufrufen gemessen:
GPT-Klasse-Modell (an einen konsistenten Upstream geroutet, Cache erreichbar):
| Aufruf | TTFT |
|---|---|
| 1. (kalt, Miss) | ~1760 ms |
| folgende (warm, Treffer) | ~1130 ms |
Caching bringt einen etwa 36 % schnelleren ersten Token und ist stabil: jeder warme Aufruf landet in einem engen Bereich.
DeepSeek-Familie-Modell (Standard-Drift, Cache selten erreichbar):
- Cache-Treffer über eine 10-Aufruf-Wiederholung: 0.
- TTFT schwankte von Aufruf zu Aufruf zwischen ~1000 ms und ~4500 ms, mit gelegentlich leeren Antworten.
Weil fast jede Anfrage einen frischen Upstream trifft, bleiben Sie bei der Cold-Prefill-Latenz und erben die Varianz desjenigen Providers, der gerade geantwortet hat. Das GPT-Modell erhielt eine 36-%-TTFT-Verbesserung durch einen erreichbaren Cache; das driftende Modell bekam keine, dazu eine 4,5x-Spanne zwischen seinem schnellsten und langsamsten Aufruf.
Prüfen Sie Ihr eigenes Setup in fünf Minuten
Vertrauen Sie nicht diesen Zahlen, oder denen von irgendjemandem. Senden Sie dasselbe lange Präfix mehrmals und beobachten Sie zwei Felder. Keine fest codierten Domains; richten Sie es per Umgebungsvariablen auf Ihr eigenes Gateway.
import os, uuid
from openai import OpenAI
client = OpenAI(api_key=os.environ["GW_KEY"], base_url=os.environ["GW_BASE"])
SYS = f"[probe {uuid.uuid4().hex}]\n\n" + ("You are a support assistant. " * 300)
seen, hits = {}, 0
for i in range(20):
r = client.chat.completions.create(
model=os.environ["GW_MODEL"], max_tokens=16,
messages=[{"role": "system", "content": SYS},
{"role": "user", "content": f"q{i}"}],
extra_body={"usage": {"include": True}})
d = r.model_dump()
det = r.usage.prompt_tokens_details
cached = (getattr(det, "cached_tokens", 0) or 0) if det else 0
seen[d.get("provider")] = seen.get(d.get("provider"), 0) + 1 # populated when exposed
hits += 1 if cached else 0
print(f"hit rate {hits}/20; upstreams seen: {len(seen)}")
Mehr als ein Upstream für dasselbe Modell bedeutet Drift. Eine Trefferquote deutlich unter Ihrer Prompt-Stabilität bedeutet, dass es Sie besteuert. Die ausführlichere Methode finden Sie in Does Your LLM Gateway Lie About Cache?.
Worauf Sie achten sollten
Die Heilung für Drift ist strukturell: Routen Sie ein bestimmtes Modell zu einem konsistenten Backend, sodass ein warmer Cache bei der nächsten Anfrage tatsächlich erreichbar ist, anstatt jeden Aufruf auf einen frischen Upstream zu verteilen, der Ihr Präfix nie gesehen hat. Wenn Sie ein Gateway bewerten, senden Sie dasselbe Präfix 20 Mal und zählen Sie die Upstreams. Einer ist das, was Sie wollen. Neun sind eine Steuer.
Ein fairer Vorbehalt: Prompt-Caching ist überall Best-Effort, und bei Disk-Cache-Modellen schwächt sich die Trefferquote über lange Leerlaufphasen selbst mit einem einzigen Backend ab. Drift zu beseitigen verschafft Ihnen keinen unendlichen Cache. Es entfernt die größte und verschwenderischste Quelle von Misses, jene, der Sie nie zugestimmt haben und die Sie nicht sehen können.
Fazit
„Unterstützt Prompt-Caching” und „Ihr Cache ist erreichbar” sind unterschiedliche Aussagen. Ein Gateway, das ein Modell über eine rotierende Besetzung von Upstreams verstreut, kann die Cache-Unterstützung wahrheitsgemäß melden und gleichzeitig eine Trefferquote von 20 %, eine ~4x-Rechnung und eine First-Token-Latenz liefern, die um das 4,5-Fache schwankt. Die Zahl, die zählt, ist nicht, ob Caching beworben wird. Es ist Ihre gemessene Trefferquote und wie viele Upstreams Ihre identischen Anfragen berühren. Führen Sie die Probe aus und lassen Sie die Daten entscheiden.
Die umfassendere Audit-Methode finden Sie in Does Your LLM Gateway Lie About Cache?; warum Caches überhaupt existieren, lesen Sie in [How K