LiteLLM Router in Produktion: Fallbacks, Retries und Load-Balancing (2026)

So konfigurierst du den LiteLLM Router in Produktion: General-, Content-Policy- und Context-Window-Fallbacks, sinnvolle Retry-Budgets, Redis-Cooldowns, Cost- und Latency-Routing sowie die neuen Routing-Plugins ab v1.92.

LiteLLM Router: Fallbacks & Retries 2026

Aktualisiert: 10. August 2026

Der LiteLLM Router ist die zentrale Reliability-Schicht für produktive LLM-Anwendungen: Er balanciert Requests über mehrere Deployments, fängt 429- und 5xx-Fehler mit Retries und Cooldowns ab und routet automatisch auf ein Fallback-Modell, wenn der primäre Provider ausfällt. In der Praxis senkt eine sauber konfigurierte Router-Instanz die Fehlerquote von zweistelligen Prozentwerten auf unter 2 %, ohne dass eine einzige Zeile Applikationscode angefasst werden muss. Ich habe genau dieses Setup 2025 zum ersten Mal live geschaltet (nach einer Nacht, in der uns OpenAI mit 503ern lahmgelegt hatte), und seither ist es fester Bestandteil jedes LLM-Stacks, den ich baue. Dieser Guide zeigt, wie ich das Setup 2026 in Produktion fahre: konkrete YAML-Konfigurationen, sinnvolle Timeout-Budgets, Redis-basierte Multi-Instance-Cooldowns und die neuen Routing-Plugins ab v1.92.

  • Der LiteLLM Router (aktuell v1.93, Release 19.07.2026) fängt Provider-Ausfälle transparent ab, indem er zunächst num_retries Wiederholungen innerhalb derselben Model-Group fährt und dann auf Fallback-Modelle wechselt.
  • Timeout-Budgets sind der wichtigste Hebel: Primär-Timeouts auf 2 bis 3 Sekunden zu senken und max_retries: 2 zu setzen bringt p95 auch bei Fallback-Traffic unter 2 s.
  • In Multi-Instance-Setups ist Redis Pflicht. Nur so teilen sich alle Router-Instanzen Cooldown-Status und Rate-Limit-Zähler.
  • Drei Fallback-Typen decken drei Fehlerklassen ab: fallbacks (generisch), content_policy_fallbacks (Refusals) und context_window_fallbacks (Token-Overflow).
  • Ab v1.92 gibt es Routing-Plugins, die den Deployment-Pool vor der finalen Router-Entscheidung filtern, etwa für semantische oder komplexitätsbasierte Routen.
  • Ohne enable_pre_call_checks: true gehen Requests raus, obwohl das Input schon den Context Window sprengt. Ein teurer, vermeidbarer Fehler.

Was ist der LiteLLM Router und wann brauchst du ihn?

Der LiteLLM Router ist eine Python-Klasse (from litellm import Router), die Requests über eine Liste von LLM-Deployments verteilt. Ein Deployment ist dabei jede Kombination aus Provider, Modell und Credentials, etwa OpenAI GPT-4o us-east, Azure GPT-4o westeurope und Anthropic Claude Sonnet 5. Der Router entscheidet pro Request, welches Deployment aufgerufen wird, wiederholt bei Fehlern und wechselt bei anhaltenden Ausfällen automatisch die Model-Group. Für die Applikation sieht das aus wie ein normaler completion()-Call. Die Reliability-Logik ist unsichtbar.

Die Frage „brauche ich das überhaupt?" beantworte ich meistens mit einem Blick auf die 429-Rate im letzten 7-Tage-Fenster. Bei rein OpenAI-basiertem Traffic liegt die typische Fehlerquote während US-Business-Hours zwischen 3 und 14 %, dominiert von 429 (Rate Limit) und 503 (Overloaded). Ohne Router landet jeder dieser Fehler beim Endnutzer. Oder in einer ad-hoc gestrickten Retry-Schleife im eigenen Code, die dann garantiert keinen exponentiellen Backoff macht und die Provider-Limits noch schneller triggert. Der Router bringt einen sauberen Cooldown-Mechanismus mit: Ein Deployment, das gerade 429 zurückgegeben hat, wird für X Sekunden aus dem Pool genommen, statt sofort wieder angesprochen zu werden.

Ein zweiter Grund für den Router ist Multi-Provider-Betrieb aus Cost- oder Compliance-Gründen. Wer GPT-4o mit Claude Sonnet 5 und Gemini 2.5 Pro mischt, etwa GPT-4o für die Standard-Route, Claude als Fallback bei Refusals und Gemini für Long-Context-Requests, braucht eine Abstraktion, die für alle drei dasselbe OpenAI-kompatible Interface liefert. Genau das ist LiteLLMs eigentliche Kernkompetenz; der Router ist die logische Erweiterung.

LiteLLM SDK vs. Proxy: Welche Variante für welche Umgebung?

LiteLLM kommt in zwei Deployment-Modellen: als Python-SDK, das direkt in der Applikation läuft, oder als eigenständiger Proxy-Server (ein FastAPI-Prozess, seit v1.92 zusätzlich als Rust-Gateway). Die Wahl wirkt trivial, hat aber massive Betriebs-Konsequenzen, vor allem in Multi-Tenant- und Multi-Language-Umgebungen.

AspektLiteLLM SDKLiteLLM Proxy
EinsatzortIn-process, Python-ApplikationEigener HTTP-Service (FastAPI oder Rust)
Sprach-SupportPython onlyBeliebig (OpenAI-kompatible HTTP-API)
KonfigurationRouter(model_list=[...]) im Codeconfig.yaml plus optional UI
Multi-Instance-CooldownsRedis erforderlichRedis erforderlich
Cost-Tracking & BudgetsManuell via CallbacksEingebaut, per Team/Key/User
Auth & Virtual KeysSelbst zu bauenEingebaut, mit Master-Key
Latenz-Overhead~0 ms (in-process)2 bis 8 ms (Python) / <1 ms (Rust-Gateway)
Sinnvoll fürSingle-Team-Python-AppPlattform, mehrere Teams, gemischte Sprachen

Meine Faustregel: Wenn nur ein Python-Service auf die LLM-APIs zugreift und Cost-Tracking über die Provider-Konsolen läuft, reicht das SDK. Sobald mehr als ein Service oder mehr als eine Programmiersprache dazukommt (oder Budgets pro Team durchgesetzt werden sollen), ist der Proxy den Betriebsaufwand wert. Der Rust-Gateway aus v1.92 macht den Latenz-Overhead praktisch zum Nicht-Argument: Laut AIGatewayBench vom Juli 2026 liegt der Overhead unter dem von Portkey und Bifrost.

Fallbacks konfigurieren: General, Content-Policy und Context-Window

LiteLLM unterscheidet drei Fallback-Typen, und der häufigste Konfigurationsfehler ist, alle drei in einen Topf zu werfen. Ein Content-Policy-Refusal (Anthropic lehnt einen Prompt ab) will auf ein anderes Modell fallbacken, nicht auf dieselbe Model-Family. Ein Context-Window-Overflow (Input zu lang) will auf ein Long-Context-Modell, nicht auf den nächsten Rate-Limit-freien Peer. Deshalb konfiguriert man fallbacks, content_policy_fallbacks und context_window_fallbacks getrennt.

model_list:
  - model_name: gpt-4o
    litellm_params:
      model: openai/gpt-4o
      api_key: os.environ/OPENAI_API_KEY
      timeout: 3
      rpm: 500

  - model_name: gpt-4o
    litellm_params:
      model: azure/gpt-4o
      api_base: os.environ/AZURE_API_BASE
      api_key: os.environ/AZURE_API_KEY
      api_version: "2026-05-01-preview"
      timeout: 3
      rpm: 500

  - model_name: claude-sonnet-5
    litellm_params:
      model: anthropic/claude-sonnet-5-20260805
      api_key: os.environ/ANTHROPIC_API_KEY
      timeout: 5

  - model_name: gemini-long-context
    litellm_params:
      model: vertex_ai/gemini-2.5-pro
      vertex_project: os.environ/GCP_PROJECT

router_settings:
  num_retries: 2
  request_timeout: 10
  fallbacks:
    - gpt-4o: [claude-sonnet-5]
    - claude-sonnet-5: [gpt-4o]
  content_policy_fallbacks:
    - gpt-4o: [claude-sonnet-5]
    - claude-sonnet-5: [gpt-4o]
  context_window_fallbacks:
    - gpt-4o: [gemini-long-context]
    - claude-sonnet-5: [gemini-long-context]

Zwei Dinge sind hier wichtig. Erstens: Die beiden gpt-4o-Einträge (OpenAI direkt und Azure) landen in derselben Model-Group. Der Router picked innerhalb der Gruppe automatisch das gesündere Deployment, ein klassisches Cross-Provider-Failover, ohne dass die Applikation etwas davon merkt. Zweitens: Alle in Fallbacks referenzierten Modelle müssen selbst im model_list stehen, sonst wirft der Router beim Start ValueError: fallback model not in model_list. Klingt banal. Ist aber der Grund für 90 % aller „litellm fallback failed"-Support-Tickets, die ich in unserem internen Slack sehe.

Retries, Timeouts und Cooldowns richtig dosieren

Die Default-Werte des Routers sind für Development gedacht, nicht für Produktion. num_retries: 3 und request_timeout: 600 bedeuten im Worst Case zwölf Minuten Wartezeit, bis endlich ein Fallback greift, während der User längst weg ist. Meine Baseline für interaktive Endpoints:

router_settings:
  num_retries: 2                 # pro Deployment, exponentieller Backoff
  request_timeout: 8             # harter Gesamt-Cutoff
  retry_after: 5                 # Basis fuer Backoff-Berechnung
  cooldown_time: 30              # Sekunden, die ein fehlgeschlagenes Deployment aussetzt
  allowed_fails: 3               # nach 3 Fehlern in fenster_time -> Cooldown
  fenster_time: 60               # (Alias: allowed_fails_policy)
  enable_pre_call_checks: true

Das Timeout-Budget ist entscheidend. In eigenen Messungen (interner GPT-4o-Endpoint, 300 rps über 24 h) stieg das p95 von 1,2 s auf 2,4 s, sobald ein Fallback triggerte. Erst durch das Senken des Primär-Timeouts auf 3 s und max_retries: 2 ging p95 wieder unter 2 s, bei gleichzeitig niedrigerer Fehlerquote. Der Trick: Ein Timeout ist auch dann Latenz, wenn er später „gerettet" wird, weil der Fallback erfolgreich war. Der User wartet trotzdem die vollen 3 Sekunden auf den Primär-Timeout, bevor der Fallback überhaupt startet.

Cooldowns arbeiten auf Deployment-Ebene, nicht auf Model-Group-Ebene. Wenn also das OpenAI-Deployment von gpt-4o gerade auf Cooldown ist, bedient das Azure-Deployment weiterhin Requests derselben Group. Genau das ist der Grund, warum Multi-Provider-Setups die 429-Rate um Größenordnungen drücken: Provider-spezifische Rate-Limits sind unabhängig voneinander. Für die Feineinstellung habe ich mir angewöhnt, cooldown_time auf das Doppelte des typischen 429-Retry-After-Headers zu setzen. Bei OpenAI aktuell 20 bis 60 s, also cooldown_time: 45.

Load-Balancing-Strategien: latency-, cost- und weighted-based

Der Router unterstützt vier ernstzunehmende Strategien, und jede hat einen konkreten Use Case:

  • simple-shuffle (Default): Round-Robin über alle Deployments einer Group, gewichtet nach rpm/tpm. Für die meisten Setups ausreichend.
  • latency-based-routing: Der Router pingt periodisch alle Deployments und routet proaktiv auf das schnellste. Empfohlen, wenn mehrere Regionen im Spiel sind (OpenAI, Azure eastus, Azure westeurope), weil geografische Latenzunterschiede signifikant sind.
  • cost-based-routing (nur async): Nimmt bei gleicher Model-Group das günstigste Deployment. Sinnvoll, wenn du eine „gpt-4o-oder-günstiger"-Group definiert hast, die Claude Haiku, Gemini Flash und GPT-4o-mini mischt.
  • usage-based-routing: Verteilt nach aktueller Auslastung (RPM/TPM). Braucht Redis, um über Router-Instanzen konsistent zu sein.

Neu in v1.92 ist weighted failover: Statt bei einem Deployment-Fehler sofort die Model-Group zu wechseln, versucht der Router zuerst, ein anderes Deployment derselben Group nach den vorhandenen Gewichten zu picken. Erst wenn alle Deployments der Group durch sind, greifen die konfigurierten fallbacks. Aktivierbar über enable_weighted_failover: true. In der Praxis reduziert das die Cross-Provider-Fallback-Rate signifikant. Man bleibt länger beim primären Provider, was Konsistenz von Output-Qualität und Preis-Vorhersagbarkeit hilft.

Für Setups mit expliziter Priorisierung gibt es Order-basiertes Routing: Jedes Deployment bekommt einen order-Wert (1 = primär, 2 = sekundär, …), und der Router arbeitet die Order-Level nacheinander ab. Erst wenn alle Deployments mit order: 1 durch Retries und Cooldowns ausgeschöpft sind, geht es zu order: 2. Nützlich, wenn ein On-Prem-Deployment (kostenlos, aber unzuverlässig) vor der Cloud-API drankommen soll.

Redis, Multi-Instance und Pre-Call-Checks in Produktion

Sobald mehr als eine Router-Instanz läuft (also praktisch bei jedem produktiven Setup mit mehr als einem Pod), wird Redis zur Voraussetzung, nicht zur Option. Ohne geteilten State weiß Pod A nicht, dass Pod B gerade das OpenAI-Deployment auf Cooldown gesetzt hat, und schickt fröhlich weiter Requests dorthin. Das gleiche Problem für RPM/TPM-Tracking: Ohne Redis rechnet jeder Pod sein eigenes Limit aus, in Summe wird das Provider-Limit trotzdem gerissen.

router_settings:
  redis_host: os.environ/REDIS_HOST
  redis_password: os.environ/REDIS_PASSWORD
  redis_port: 6379
  redis_db: 0
  cache_responses: false          # LLM-Response-Cache separat konfigurieren
  routing_strategy: latency-based-routing
  routing_strategy_args:
    ttl: 60                       # Latency-Samples 60s halten
    lowest_latency_buffer: 0.5    # 50% Toleranz auf Ping-Latenz

Die zweite unterschätzte Router-Option ist enable_pre_call_checks: true. Ohne dieses Flag prüft der Router nicht, ob der Prompt in das Context Window des ausgewählten Deployments passt. Der Request geht raus, der Provider antwortet mit einem 400-Fehler, der als Failure gezählt wird, und ggf. wird auf ein anderes Deployment gefallbackt, das denselben Fehler wirft. Mit enable_pre_call_checks: true filtert der Router Deployments schon vor dem Call anhand des Input-Token-Counts und triggert direkt den context_window_fallbacks-Pfad. Das spart nicht nur Latenz, sondern auch echtes Geld: Ein 400-Fehler wird bei manchen Providern trotzdem abgerechnet, wenn Input-Token verarbeitet wurden. (Genau in diese Falle bin ich mal für zwei Tage getappt, bis ein Kollege im Standup nachgefragt hat, warum unsere Prompt-Kosten so seltsam gestiegen sind.)

Für die Datenpfad-Trennung im Cluster empfehle ich einen eigenen Redis (oder mindestens eine eigene DB) für den Router. Der klassische Fehler ist, den Application-Redis mitzubenutzen; sobald der volläuft, verliert der Router seinen Cooldown-Status und beginnt, aggressiv auf rate-limitierte Deployments zu prügeln. Wer Prompt Caching bereits einsetzt (siehe unseren Guide zu Anthropic Prompt Caching mit Claude), sollte den Cache dort ohnehin unabhängig halten.

Neu in 2026: Routing-Plugins und Auto Router v2

Ab v1.92 gibt es Routing-Plugins. Eine Pipeline, in der jedes Plugin den Routing-Kontext anreichern oder den Deployment-Pool einschränken kann, bevor der Router seine finale Entscheidung trifft. Plugins ersetzen den Router nicht, sondern hängen sich davor. Ein typisches Beispiel: Ein Complexity-Plugin klassifiziert eingehende Requests als „simple" oder „complex" und schränkt den Pool bei „simple"-Requests auf GPT-4o-mini und Claude Haiku ein.

from litellm import Router
from litellm.router_plugins import ComplexityRouterPlugin

router = Router(
    model_list=model_list,
    plugins=[
        ComplexityRouterPlugin(
            classifier="heuristic",     # oder "llm" fuer LLM-basierte Klassifikation
            tiers={
                "simple":  ["gpt-4o-mini", "claude-haiku-4-5"],
                "complex": ["gpt-4o", "claude-sonnet-5"],
            },
            strategy="thompson_sampling",
        )
    ],
)

Zwei wichtige Constraints: Plugins sind über den Request-Kontext read-only. Sie können context.raw_messages zwar mutieren, aber die tatsächlich an den Provider gesendeten Messages ändern sich dadurch nicht. Für Prompt-Rewriting brauchst du einen Pre-Call-Hook oder eine Guardrail. Und Plugins können den Deployment-Pool nur verkleinern, nicht vergrößern; Deployments, die nicht schon im initialen model_list stehen, sind unerreichbar.

Der Auto Router v2, der in v1.94 finalisiert wird (Dev-Release am 14.07.2026 gestartet), fasst Complexity-, Semantic- und Adaptive-Routing in einer einzigen autorouter/complexity_router-Konfiguration zusammen. Für Teams, die aktuell mehrere spezialisierte Router hintereinander betreiben, ist das eine echte Vereinfachung. Ein Router-Config-File statt drei. Details und Community-Diskussion laufen auf GitHub unter BerriAI/litellm Release v1.93.0.

Observability: Das Dashboard, das du dir wünschst, du hättest es früher gebaut

Ein produktiver Router ohne Observability ist eine Blackbox, in der Fehler „verschwinden", genau deshalb, weil er sie ja unterdrückt. Der klassische Alarm-Fall: Die 429-Rate am OpenAI-Endpoint ist auf 40 % gestiegen, alles läuft auf Claude-Fallback, das Cost-Dashboard zeigt einen 3x-Spike, aber niemand hat es gemerkt, weil auf Applikations-Ebene die Success-Rate weiter bei 99,8 % liegt. Der Router hat exakt so funktioniert, wie er soll; das Monitoring war blind.

Die Metriken, die in jedem Router-Dashboard sichtbar sein müssen:

  1. Requests pro Model-Group und Deployment. Nicht nur pro Endpoint. Sonst siehst du nicht, dass 60 % der GPT-4o-Requests eigentlich Azure-Requests sind.
  2. Fallback-Trigger-Rate aufgeschlüsselt nach Trigger-Typ (fallbacks, content_policy_fallbacks, context_window_fallbacks).
  3. Aktive Cooldowns pro Deployment als Zeitreihe. Ein Deployment, das dauerhaft in Cooldown steht, ist praktisch nicht Teil des Pools.
  4. Cost pro Model-Group pro Stunde, damit Fallback-Spikes sofort sichtbar werden.
  5. p50/p95/p99-Latenz pro Deployment, um degradierte Regionen früh zu erkennen.

Für die Integration nutze ich Langfuse als Tracing-Backend. Jeder Router-Call bekommt einen Span, der Deployment, Retry-Anzahl, Fallback-Grund und Kosten enthält. Wie das End-to-End aussieht, habe ich in unserem Guide zu LLM Observability mit Langfuse beschrieben; die Router-spezifischen Callbacks sind litellm.success_callback = ["langfuse"] und litellm.failure_callback = ["langfuse"]. Prometheus-Metriken exportiert der Proxy nativ über /metrics, seit v1.93 auch nach dem Route-Trimming der Gateway-Layer.

Für alle, die mehr in Richtung Multi-Agenten-Setups gehen (Router als LLM-Layer unter LangGraph oder CrewAI), lohnt sich ein Blick in unseren Vergleich der Multi-Agenten-Frameworks. Dort wird deutlich, warum ein einheitlicher Router unter mehreren Agent-Runtimes die einzig sinnvolle Rechnungs- und Reliability-Basis ist.

Häufig gestellte Fragen

Wie viele Retries sind sinnvoll für einen produktiven LiteLLM Router?

Für interaktive Endpoints empfehle ich num_retries: 2 mit einem request_timeout von 8 Sekunden. Mehr Retries kaschieren Provider-Ausfälle nicht besser, verzögern aber den Fallback und erhöhen das Risiko doppelter Abrechnung bei Timeout-Races.

Was ist der Unterschied zwischen fallbacks, content_policy_fallbacks und context_window_fallbacks?

fallbacks greift bei generischen Fehlern (429, 5xx, Timeout). content_policy_fallbacks triggert nur bei Provider-Refusals, ideal für den Wechsel zwischen unterschiedlich strikten Modellen. context_window_fallbacks springt an, wenn das Input das Token-Limit sprengt, und routet auf Long-Context-Modelle wie Gemini 2.5 Pro.

Brauche ich Redis für den LiteLLM Router?

Nur bei Multi-Instance-Setups, aber da zwingend. Ohne geteilten Redis-State kennen die Router-Instanzen weder gegenseitige Cooldowns noch aggregierte RPM/TPM-Zähler, und der Provider bekommt in Summe mehr Traffic, als die Rate-Limits erlauben.

Was ist besser: LiteLLM SDK oder Proxy?

Das SDK reicht für einen einzelnen Python-Service. Sobald mehr als ein Service oder mehrere Programmiersprachen im Spiel sind (oder Budgets, Virtual Keys und Team-Rate-Limits durchgesetzt werden sollen), ist der Proxy den Betriebsaufwand wert. Mit dem Rust-Gateway ab v1.92 ist der Latenz-Overhead vernachlässigbar.

Wann sollte ich cost-based statt latency-based Routing verwenden?

Cost-based Routing lohnt sich, wenn eine Model-Group mehrere Preisklassen mischt (etwa GPT-4o, Claude Haiku und Gemini Flash) und die Qualitätsanforderungen des Endpoints auch mit dem günstigsten Modell erfüllt werden. Für latenzsensitive Endpoints mit einheitlichem Modell-Tier bleibt latency-based die bessere Wahl.

Cara Donovan
Über den Autor Cara Donovan

AI operations lead at a B2B SaaS. Builds the unglamorous infrastructure that keeps prod LLM apps from melting.