[{"data":1,"prerenderedAt":812},["ShallowReactive",2],{"blog-llm-rate-limits-retries-provider-fallback-de":3},{"slug":4,"published":5,"minutes":6,"category":7,"tags":8,"keywords":14,"about":26,"sources":36,"cover":67,"og":68,"expertise":69,"locales":70,"lang":72,"title":74,"description":75,"coverAlt":76,"metaTitle":77,"takeaways":78,"faq":84,"toc":100,"blocks":131,"others":584},"llm-rate-limits-retries-provider-fallback","2026-10-17",10,"llmops",[9,10,11,12,13],"Rate limits","Retries","Fallback","Reliability","LLM gateway",[15,16,17,18,19,20,21,22,23,24,25],"llm rate limit handling","429 too many requests llm api","exponential backoff with jitter","anthropic 529 overloaded error","openai rate limit retry","llm provider fallback","litellm fallbacks","retry-after header","llm circuit breaker","multi provider llm failover","claude api rate limits",[27,30,33],{"name":28,"url":29},"Token bucket","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FToken_bucket",{"name":31,"url":32},"Exponential backoff","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FExponential_backoff",{"name":34,"url":35},"Circuit breaker design pattern","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FCircuit_breaker_design_pattern",[37,40,43,46,49,52,55,58,61,64],{"title":38,"url":39},"Claude Platform Docs: Rate limits","https:\u002F\u002Fplatform.claude.com\u002Fdocs\u002Fen\u002Fapi\u002Frate-limits",{"title":41,"url":42},"Claude Platform Docs: API errors","https:\u002F\u002Fplatform.claude.com\u002Fdocs\u002Fen\u002Fapi\u002Ferrors",{"title":44,"url":45},"OpenAI API Docs: Rate limits","https:\u002F\u002Fdevelopers.openai.com\u002Fapi\u002Fdocs\u002Fguides\u002Frate-limits",{"title":47,"url":48},"AWS Builders Library: Timeouts, retries and backoff with jitter","https:\u002F\u002Fbuilder.aws.com\u002Fcontent\u002F3EumjoZascWd1oZiEgL8ORlv3qE\u002Ftimeouts-retries-and-backoff-with-jitter",{"title":50,"url":51},"MDN: Retry-After header","https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FHTTP\u002FReference\u002FHeaders\u002FRetry-After",{"title":53,"url":54},"Martin Fowler: Circuit Breaker (2014)","https:\u002F\u002Fmartinfowler.com\u002Fbliki\u002FCircuitBreaker.html",{"title":56,"url":57},"LiteLLM Docs: Router, retries and cooldowns","https:\u002F\u002Fdocs.litellm.ai\u002Fdocs\u002Frouting",{"title":59,"url":60},"LiteLLM Docs: Proxy fallbacks and reliability","https:\u002F\u002Fdocs.litellm.ai\u002Fdocs\u002Fproxy\u002Freliability",{"title":62,"url":63},"OpenRouter Docs: Model fallbacks","https:\u002F\u002Fopenrouter.ai\u002Fdocs\u002Fguides\u002Frouting\u002Fmodel-fallbacks",{"title":65,"url":66},"AI SDK Docs: Settings (maxRetries, timeout)","https:\u002F\u002Fai-sdk.dev\u002Fdocs\u002Fai-sdk-core\u002Fsettings","\u002Fimages\u002Fblog\u002Fllm-rate-limits-retries-provider-fallback\u002Fcover.webp","\u002Fimages\u002Fblog\u002Fllm-rate-limits-retries-provider-fallback\u002Fog.jpg","ai-engineer",[71,72,73],"en","de","hu","LLM-Rate-Limits in Produktion: Retries, Backoff und Provider-Fallback","Wie LLM-Rate-Limits funktionieren, welche Fehler man wiederholt, Backoff mit Jitter, Retries in nur einer Schicht und Fallback-Ketten ohne kaputte Ausgaben.","Kleine Quadrate steigen drei Stufen zu einem breiten Rechteck, dahinter zwei weitere in einer Reihe.","LLM-Rate-Limits: Retries und Fallback · Balázs Csorba",[79,80,81,82,83],"Provider-Limits sind Token-Buckets, gemessen pro Minute in Anfragen und Tokens, aber über kürzere Intervalle durchgesetzt, deshalb scheitern Bursts auch bei unauffälliger Minutensumme.","Fehler vor dem Retry klassifizieren: 429 mit retry-after und 5xx sind vorübergehend, ein 429 wegen Ausgabenlimit, 400er und Auth-Fehler nicht.","Exponentielles Backoff mit Jitter verwenden, retry-after als Minimum respektieren und sowohl Versuche als auch Gesamtzeit begrenzen.","Retries in genau einer Schicht. SDK-, Gateway- und App-Retries multiplizieren sich, und das AWS-Beispiel zeigt, wie schnell das wächst.","Ein Fallback-Modell ist ein anderes Produkt: es auf dem eigenen Testsatz evaluieren, bevor es Produktionsverkehr bedient.",[85,88,91,94,97],{"q":86,"a":87},"Was ist der Unterschied zwischen 429 und 529 bei der Claude API?","Ein 429 rate_limit_error bedeutet, dass die eigene Organisation ein eigenes Limit erreicht hat, etwa Anfragen oder Tokens pro Minute oder das monatliche Ausgabenlimit. Ein 529 overloaded_error bedeutet, dass die API vorübergehend für alle Nutzer überlastet ist. Beide lohnen meist einen verzögerten Retry, außer dem 429 wegen Ausgabenlimit: er hat keinen retry-after-Header und scheitert weiter, bis der Zugang wieder freigegeben ist.",{"q":89,"a":90},"Wie oft sollte man eine LLM-Anfrage wiederholen?","Zwei bis vier Versuche mit exponentiellem Backoff sind üblich, und sowohl das Anthropic-SDK als auch das Vercel AI SDK wiederholen standardmäßig zweimal. Wichtiger als die Zahl ist eine Obergrenze für die Gesamtzeit, damit eine Nutzeranfrage nicht minutenlang hängt, und dass nur eine Schicht im Stack wiederholt.",{"q":92,"a":93},"Zählt max_tokens gegen die Rate-Limits?","Das hängt vom Anbieter ab. Anthropic schreibt, dass max_tokens nicht in das Output-Token-Limit eingeht, das nur erzeugte Tokens zählt. OpenAI rechnet die Anfrage mit dem Maximum aus max_tokens und der geschätzten Tokenzahl gegen das Limit, ein überdimensioniertes max_tokens verbraucht also Spielraum.",{"q":95,"a":96},"LiteLLM, OpenRouter oder eigener Code für Fallbacks?","Wer schon ein Gateway betreibt, konfiguriert Fallbacks dort und schaltet Retries anderswo ab. LiteLLM bietet Retry-Policies pro Fehlertyp, Cooldowns und Kontextfenster-Fallbacks zum Selbsthosten; OpenRouter bietet ein models-Array hinter einem API-Key. Eigener Code reicht für ein oder zwei Anbieter, aber am Ende baut man Cooldowns nach.",{"q":98,"a":99},"Ist ein Fallback auf einen anderen Anbieter bei strukturierter Ausgabe sicher?","Nur wenn man es getestet hat. Anbieter unterscheiden sich darin, wie sie JSON Schema durchsetzen, welche Features sie unterstützen und wie sie Ablehnungen formulieren. Denselben Evaluationssatz gegen das Fallback-Modell laufen lassen und jede Antwort gegen das Schema validieren, egal welches Modell sie erzeugt hat.",[101,104,107,110,113,116,119,122,125,128],{"id":102,"title":103},"how-limits-work","Wie Provider-Rate-Limits tatsächlich funktionieren",{"id":105,"title":106},"classify-errors","Den Fehler klassifizieren, bevor man wiederholt",{"id":108,"title":109},"backoff-jitter","Exponentielles Backoff mit Jitter und einer Deadline",{"id":111,"title":112},"retry-one-layer","Retries in genau einer Schicht",{"id":114,"title":115},"fallback-chain","Eine Fallback-Kette aufbauen",{"id":117,"title":118},"fallback-pitfalls","Warum Fallbacks das Produkt stillschweigend verändern",{"id":120,"title":121},"circuit-breakers","Cooldowns und Circuit Breaker",{"id":123,"title":124},"raise-the-ceiling","Die Decke anheben, bevor man sie erreicht",{"id":126,"title":127},"timeouts-streaming","Timeouts und lange Anfragen",{"id":129,"title":130},"sources","Quellen",[132,136,139,142,145,156,218,221,222,225,284,305,308,309,315,317,320,321,335,363,364,367,376,413,415,416,419,461,462,473,476,477,485,519,520,537,549,550],{"type":133,"content":134},"paragraph",[135],"Jedes LLM-Feature, das echten Verkehr bekommt, trifft irgendwann auf einen 429. Manchmal ist man selbst schuld, etwa weil ein Batch-Job denselben Key wie der Chat-Endpunkt nutzt. Manchmal liegt es am Anbieter, der zu Stoßzeiten überlastet ist. So oder so sieht der Nutzer einen Spinner und dann einen Fehler, und die übliche Reaktion ist, den Aufruf in eine Retry-Schleife zu packen und weiterzumachen. Das rettet die Demo und erzeugt den nächsten Ausfall.",{"type":133,"content":137},[138],"Dieser Leitfaden zeigt, was hinter einem Rate-Limit tatsächlich passiert, welche Fehler einen Retry verdienen und welche nie, wie man zurückweicht, ohne alle Clients zu synchronisieren, warum Retries in genau eine Schicht gehören und wie man eine Fallback-Kette zu einem anderen Deployment oder Anbieter baut, ohne stillschweigend zu ändern, was das Feature zurückgibt. Die Zahlen stammen aus der Dokumentation von Anthropic und OpenAI, Stand Oktober 2026.",{"type":140,"level":141,"id":102,"text":103},"heading",2,{"type":133,"content":143},[144],"Anthropic misst die Limits der Messages API in Anfragen pro Minute (RPM), Input-Tokens pro Minute (ITPM) und Output-Tokens pro Minute (OTPM), jeweils pro Modellklasse, und verwendet einen Token-Bucket: die Kapazität füllt sich laufend bis zum Maximum auf, statt zu jeder vollen Minute zurückgesetzt zu werden. Die Dokumentation nennt ein Detail, das viele rätselhafte 429er erklärt: ein Limit von 60 RPM kann als eine Anfrage pro Sekunde durchgesetzt werden, ein kurzer Burst scheitert also, obwohl die Minute insgesamt unter dem Limit bleibt.",{"type":133,"content":146},[147,148,152,153,155],"OpenAI zählt Anfragen und Tokens pro Minute und pro Tag sowie Bilder pro Minute, und was zuerst erreicht wird, löst den Fehler aus. Zwei weitere Details sind fürs Design wichtig. OpenAI rechnet eine Anfrage mit dem Maximum aus ",{"tag":149,"children":150},"code",[151],"max_tokens"," und der geschätzten Anfragegröße gegen das Token-Limit, ein großzügiges ",{"tag":149,"children":154},[151]," frisst also Spielraum; Anthropic schreibt für sein Output-Limit das Gegenteil, dort zählen nur erzeugte Tokens. Und OpenAI weist darauf hin, dass auch fehlgeschlagene Anfragen gegen das Minutenlimit zählen, weshalb enge Retry-Schleifen einen 429 schlimmer statt besser machen.",{"type":157,"head":158,"rows":165},"table",[159,161,163],[160],"Aspekt",[162],"Anthropic Claude API",[164],"OpenAI API",[166,173,180,186,204,211],[167,169,171],[168],"Dimensionen",[170],"RPM, ITPM, OTPM",[172],"RPM, RPD, TPM, TPD, IPM",[174,176,178],[175],"Gecachter Input",[177],"Cache-Reads zählen bei den meisten Modellen nicht zum ITPM",[179],"Zählt zum TPM",[181,182,184],[151],[183],"Zählt nicht; OTPM nutzt erzeugte Tokens",[185],"Zählt als max(max_tokens, Schätzung)",[187,189,197],[188],"Header",[190,193,194],{"tag":149,"children":191},[192],"anthropic-ratelimit-*",", ",{"tag":149,"children":195},[196],"retry-after",[198,193,201],{"tag":149,"children":199},[200],"x-ratelimit-*",{"tag":149,"children":202},[203],"Retry-After",[205,207,209],[206],"Retry-After kommt bei",[208],"Den meisten 429ern, nicht beim Ausgabenlimit-429",[210],"429- und 503-Antworten",[212,214,216],[213],"Burst-Schutz",[215],"Beschleunigungslimits bei starkem Anstieg",[217],"Kürzere Durchsetzungsfenster",{"type":133,"content":219},[220],"Anthropic wendet außerdem Beschleunigungslimits an: steigt die Nutzung der Organisation stark an, kann man 429er auch unterhalb der Tier-Limits bekommen, und die Empfehlung lautet, den Verkehr schrittweise hochzufahren. Das zählt am Launch-Tag und wenn ein Backfill-Job mit voller Geschwindigkeit startet.",{"type":140,"level":141,"id":105,"text":106},{"type":133,"content":223},[224],"Ein Retry ist nur sinnvoll, wenn der nächste Versuch ohne jede Änderung gelingen kann. Die meisten Retry-Bugs entstehen, weil man jeden Nicht-200-Status gleich behandelt. Die Fehlerliste der Claude API macht die Trennung recht klar:",{"type":157,"head":226,"rows":233},[227,229,231],[228],"Antwort",[230],"Bedeutung",[232],"Was tun",[234,243,253,267,277],[235,239,241],[236,237],"429 + ",{"tag":149,"children":238},[196],[240],"Ein Rate-Limit wurde erreicht",[242],"Mindestens retry-after warten, dann wiederholen",[244,249,251],[245,246],"429 ohne retry-after, ",{"tag":149,"children":247},[248],"enforced_spend_limit_reached",[250],"Monatliches Ausgabenlimit des Tiers erreicht",[252],"Nicht wiederholen; Menschen alarmieren oder umschalten",[254,263,265],[255,256,259,260],"500 ",{"tag":149,"children":257},[258],"api_error",", 529 ",{"tag":149,"children":261},[262],"overloaded_error",[264],"Vorübergehendes Serverproblem",[266],"Zurückweichen, wiederholen, dann Fallback",[268,273,275],[269,270],"504 ",{"tag":149,"children":271},[272],"timeout_error",[274],"Zeitüberschreitung bei der Verarbeitung",[276],"Einmal wiederholen; lange Anfragen streamen",[278,280,282],[279],"400, 401, 403, 404, 413",[281],"Die Anfrage selbst ist falsch oder ein selbst gesetztes Ausgabenlimit (400)",[283],"Nie unverändert wiederholen; loggen und beheben",{"type":285,"variant":286,"title":287,"body":288},"callout","warn","Nicht jeder 429 ist vorübergehend",[289],[290,291,294,295,297,298,301,302,304],"Erreicht eine Anthropic-Organisation das Ausgabenlimit ihres Tiers, liefert die API einen 429 mit Fehlertyp ",{"tag":149,"children":292},[293],"rate_limit_error",", ohne ",{"tag":149,"children":296},[196],"-Header und mit ",{"tag":149,"children":299},[300],"error.details.error_code"," gleich ",{"tag":149,"children":303},[248],". Die Nutzung bleibt bis zum Ersten des Folgemonats um 00:00 UTC pausiert. Eine generische Retry-Schleife, auch die des SDK, rennt weiter gegen eine Wand. Diesen Code erkennen, Retries stoppen und jemanden alarmieren.",{"type":133,"content":306},[307],"Streaming fügt einen weiteren Fall hinzu. Bei Server-Sent Events kann ein Fehler eintreffen, nachdem die API bereits 200 geliefert hat, statusbasierte Retry-Logik sieht ihn also nie. Ob man eine halb gestreamte Antwort wiederholt, ist eine Produktentscheidung: in einer Chat-Oberfläche zeigt man, was angekommen ist, und bietet einen Retry-Button an; in einem Hintergrundjob verwirft man die Teilausgabe und wiederholt die ganze Anfrage.",{"type":140,"level":141,"id":108,"text":109},{"type":133,"content":310},[311,312,314],"Der OpenAI-Leitfaden und die AWS Builders Library sind sich in der Form einig: kurz warten, nach jedem Fehler länger, Zufall hinzufügen, damit Clients nicht im Gleichschritt wiederholen, und nach einer Grenze aufhören. OpenAI ergänzt, dass ",{"tag":149,"children":313},[203]," als Minimum gilt, nicht als Vorschlag. Laut HTTP-Semantik enthält der Header entweder Sekunden oder ein HTTP-Datum, also beides parsen.",{"type":149,"code":316},"\u002F\u002F One retry wrapper for the whole app. Turn SDK retries off (maxRetries: 0) when you use it.\nconst RETRYABLE = new Set([408, 429, 500, 502, 503, 504, 529])\n\nfunction retryAfterMs(h: Headers): number | null {\n  const v = h.get('retry-after')\n  if (!v) return null\n  const s = Number(v)\n  if (!Number.isNaN(s)) return s * 1000\n  const t = Date.parse(v)              \u002F\u002F HTTP-date form\n  return Number.isNaN(t) ? null : Math.max(0, t - Date.now())\n}\n\nexport async function withRetry\u003CT>(call: () => Promise\u003CResponse>, parse: (r: Response) => Promise\u003CT>,\n  { attempts = 4, baseMs = 500, capMs = 20_000, deadlineMs = 45_000 } = {}): Promise\u003CT> {\n  const start = Date.now()\n  for (let i = 0; ; i++) {\n    const res = await call()\n    if (res.ok) return parse(res)\n    const body = await res.clone().json().catch(() => ({}))\n    const spendCap = body?.error?.details?.error_code === 'enforced_spend_limit_reached'\n    if (!RETRYABLE.has(res.status) || spendCap || i + 1 >= attempts) throw new Error(`LLM ${res.status}`)\n    const backoff = Math.random() * Math.min(capMs, baseMs * 2 ** i)   \u002F\u002F \"full jitter\"\n    const wait = Math.max(retryAfterMs(res.headers) ?? 0, backoff)\n    if (Date.now() - start + wait > deadlineMs) throw new Error(`LLM ${res.status}: retry budget spent`)\n    await new Promise((r) => setTimeout(r, wait))\n  }\n}",{"type":133,"content":318},[319],"Die Deadline zählt so viel wie die Zahl der Versuche. Eine Chat-Anfrage, die nach 45 Sekunden noch wiederholt, ist gescheitert, egal was danach passiert, also früh aufgeben und die Fallback-Kette oder die Oberfläche übernehmen lassen. Hintergrundjobs vertragen längere Deadlines, sollten aber auch deutlich stärker zurückweichen, denn sie konkurrieren mit dem interaktiven Verkehr um dieselben Limits.",{"type":140,"level":141,"id":111,"text":112},{"type":133,"content":322},[323,324,326,327,330,331,334],"Der AWS-Artikel enthält die klarste Warnung: bei einem fünf Ebenen tiefen Aufrufstapel, in dem jede Ebene dreimal wiederholt, kann die Last auf der untersten Abhängigkeit um das 243-Fache wachsen. LLM-Stacks verstecken dieselbe Falle. Das Anthropic-SDK wiederholt Verbindungsfehler, 429er und 5xx standardmäßig zweimal und respektiert ",{"tag":149,"children":325},[196],". Das Vercel AI SDK hat ",{"tag":149,"children":328},[329],"maxRetries"," mit Standardwert 2. Ein Gateway wie LiteLLM hat ",{"tag":149,"children":332},[333],"num_retries",". Wiederholt zusätzlich der eigene Code, wird ein Klick während eines Vorfalls zu Dutzenden Upstream-Aufrufen, genau dann, wenn der Anbieter sie am wenigsten verkraftet.",{"type":336,"items":337},"list",[338,344,353,358],[339,343],{"tag":340,"children":341},"strong",[342],"Die Schicht wählen, die am meisten weiß."," Meist das Gateway, falls vorhanden, weil es den gesamten Verkehr und alle Deployments sieht. Sonst der eigene Wrapper.",[345,348,349,352],{"tag":340,"children":346},[347],"Überall sonst Retries auf null setzen."," ",{"tag":149,"children":350},[351],"maxRetries: 0"," im SDK-Client, keine Schleifen in Route-Handlern.",[354,357],{"tag":340,"children":355},[356],"Ein Retry-Budget einführen."," AWS begrenzt lokale Retries mit einem Token-Bucket: solange Tokens da sind, laufen Retries frei, danach nur noch mit fester Rate. So verdoppelt ein Ausfall nicht das Anfragevolumen.",[359,362],{"tag":340,"children":360},[361],"Seiteneffekte zuerst idempotent machen."," Ein Agentenschritt, der eine E-Mail sendet oder eine Bestellung schreibt, darf nicht doppelt laufen, weil der Modellaufruf danach wiederholt wurde.",{"type":140,"level":141,"id":114,"text":115},{"type":133,"content":365},[366],"Retries helfen bei kurzen Aussetzern. Bleibt ein Modell unerreichbar oder ist das Limit dafür erschöpft, braucht die Anfrage ein anderes Ziel. Ich ordne die Optionen danach, wie stark sie die Ausgabe verändern: zuerst dasselbe Modell auf einem anderen Deployment oder in einer anderen Region, dann ein Geschwistermodell desselben Anbieters, zuletzt ein anderer Anbieter und am Ende eine kontrollierte Degradierung (gecachte Antwort, einfacheres Feature, ehrliche Fehlermeldung).",{"type":368,"attrs":369,"inner":373,"caption":374},"diagram",{"viewBox":370,"role":371,"aria-labelledby":372},"0 0 720 170","img","rlf1-t rlf1-d","\u003Ctitle id=\"rlf1-t\">Fallback-Kette, geordnet nach Veränderung der Ausgabe\u003C\u002Ftitle>\u003Cdesc id=\"rlf1-d\">Eine Anfrage wiederholt zuerst mit Backoff, wechselt dann zum selben Modell auf einem anderen Deployment, dann zu einem Geschwistermodell, dann zu einem anderen Anbieter und degradiert am Ende kontrolliert.\u003C\u002Fdesc>\u003Cdefs>\u003Cmarker id=\"rlf1-ah\" viewBox=\"0 0 10 10\" refX=\"9\" refY=\"5\" markerWidth=\"7\" markerHeight=\"7\" orient=\"auto-start-reverse\">\u003Cpath d=\"M0 0L10 5L0 10z\" class=\"d-head\" \u002F>\u003C\u002Fmarker>\u003C\u002Fdefs>\u003Crect x=\"20\" y=\"47\" width=\"118\" height=\"76\" rx=\"10\" class=\"d-box\" \u002F>\u003Ctext x=\"79\" y=\"81\" text-anchor=\"middle\" class=\"d-text\">Retry\u003C\u002Ftext>\u003Ctext x=\"79\" y=\"103\" text-anchor=\"middle\" class=\"d-small\">Backoff + Jitter\u003C\u002Ftext>\u003Cpath d=\"M138 85H158\" class=\"d-line\" marker-end=\"url(#rlf1-ah)\" \u002F>\u003Crect x=\"160\" y=\"47\" width=\"118\" height=\"76\" rx=\"10\" class=\"d-mint\" \u002F>\u003Ctext x=\"220\" y=\"81\" text-anchor=\"middle\" class=\"d-text\">Gleiches Modell\u003C\u002Ftext>\u003Ctext x=\"220\" y=\"103\" text-anchor=\"middle\" class=\"d-small\">andere Region\u003C\u002Ftext>\u003Cpath d=\"M279 85H299\" class=\"d-line\" marker-end=\"url(#rlf1-ah)\" \u002F>\u003Crect x=\"301\" y=\"47\" width=\"118\" height=\"76\" rx=\"10\" class=\"d-sky\" \u002F>\u003Ctext x=\"360\" y=\"81\" text-anchor=\"middle\" class=\"d-text\">Geschwister\u003C\u002Ftext>\u003Ctext x=\"360\" y=\"103\" text-anchor=\"middle\" class=\"d-small\">gleicher Anbieter\u003C\u002Ftext>\u003Cpath d=\"M419 85H439\" class=\"d-line\" marker-end=\"url(#rlf1-ah)\" \u002F>\u003Crect x=\"441\" y=\"47\" width=\"118\" height=\"76\" rx=\"10\" class=\"d-gold\" \u002F>\u003Ctext x=\"500\" y=\"81\" text-anchor=\"middle\" class=\"d-text\">Anderer Anbieter\u003C\u002Ftext>\u003Ctext x=\"500\" y=\"103\" text-anchor=\"middle\" class=\"d-small\">vorher evaluiert\u003C\u002Ftext>\u003Cpath d=\"M560 85H580\" class=\"d-line\" marker-end=\"url(#rlf1-ah)\" \u002F>\u003Crect x=\"582\" y=\"47\" width=\"118\" height=\"76\" rx=\"10\" class=\"d-box\" \u002F>\u003Ctext x=\"641\" y=\"81\" text-anchor=\"middle\" class=\"d-text\">Degradieren\u003C\u002Ftext>\u003Ctext x=\"641\" y=\"103\" text-anchor=\"middle\" class=\"d-small\">ehrlicher Fehler\u003C\u002Ftext>",[375],"Je weiter rechts eine Anfrage landet, desto stärker kann ihre Ausgabe vom Getesteten abweichen.",{"type":133,"content":377},[378,379,384,385,388,389,392,393,395,396,399,400,403,404,408,409,412],"Selbst schreiben muss man das selten. ",{"tag":380,"to":381,"children":382},"link","\u002Ftools\u002Flitellm",[383],"LiteLLM"," nimmt in ",{"tag":149,"children":386},[387],"router_settings"," eine ",{"tag":149,"children":390},[391],"fallbacks","-Liste, die eine Modellgruppe auf geordnete Ersatzmodelle abbildet und nach ",{"tag":149,"children":394},[333]," Versuchen greift. Dazu gibt es ",{"tag":149,"children":397},[398],"context_window_fallbacks"," für zu lange Prompts und ",{"tag":149,"children":401},[402],"content_policy_fallbacks"," für Ablehnungen durch einen Provider-Filter. ",{"tag":380,"to":405,"children":406},"\u002Ftools\u002Fopenrouter",[407],"OpenRouter"," nimmt ein ",{"tag":149,"children":410},[411],"models","-Array in Prioritätsreihenfolge, probiert bei einem Fehler das nächste Modell, auch bei Rate-Limits, Ausfällen und Kontextlängenfehlern, und berechnet das Modell, das die Anfrage tatsächlich bearbeitet hat.",{"type":149,"code":414},"# LiteLLM proxy: retries live here, nowhere else\nrouter_settings:\n  num_retries: 2\n  allowed_fails: 3        # failures per minute before a deployment cools down\n  cooldown_time: 30       # seconds the deployment is skipped\n  retry_policy:\n    RateLimitErrorRetries: 3\n    BadRequestErrorRetries: 0\n    AuthenticationErrorRetries: 0\n    DefaultRetries: 2\n  fallbacks: [{\"support-primary\": [\"support-secondary\"]}]\n  enable_pre_call_checks: true   # needed for context-window fallbacks to check input size",{"type":140,"level":141,"id":117,"text":118},{"type":133,"content":417},[418],"Ein Fallback, der 200 liefert, kann trotzdem ein Fehlschlag sein. Auf ein Modell abgestimmte Prompts verhalten sich auf einem anderen oft anders; Unterstützung für strukturierte Ausgabe und JSON-Schema-Abdeckung unterscheiden sich zwischen Anbietern; Tool-Calling-Formate und Ablehnungsstile sind verschieden; und Prompt-Caches gelten pro Anbieter, die ersten Minuten auf einem Fallback sind also teurer und langsamer. Teams merken das, wenn der Vorfall vorbei ist und Support-Tickets von seltsamen Antworten berichten.",{"type":336,"items":420},[421,431,436,446,451],[422,425,426,430],{"tag":340,"children":423},[424],"Den Fallback wie eine Migration evaluieren."," Den Regressionssatz gegen jedes Modell der Kette laufen lassen, wie in ",{"tag":380,"to":427,"children":428},"\u002Fblog\u002Fllm-model-migration-regression-testing",[429],"LLM-Modellmigrationen ohne Regressionen"," beschrieben.",[432,435],{"tag":340,"children":433},[434],"Einen Prompt pro Modell pflegen."," Ein Fallback-Eintrag ist Modell plus Prompt und Parameter, nicht nur ein Modellname.",[437,440,441,445],{"tag":340,"children":438},[439],"Ausgabe unabhängig von der Quelle validieren."," Schema-Validierung und fachliche Prüfungen laufen bei jeder Antwort; ",{"tag":380,"to":442,"children":443},"\u002Fblog\u002Fstructured-outputs-json-schema-llm",[444],"strukturierte Ausgaben"," machen sie nicht überflüssig.",[447,450],{"tag":340,"children":448},[449],"Festhalten, welches Modell geantwortet hat."," Das bedienende Modell in die Traces schreiben, damit Qualitäts-Dashboards nicht zwei Produkte zu einer Linie vermischen.",[452,455,456,460],{"tag":340,"children":453},[454],"Datenresidenz prüfen."," Ein Fallback von einer EU-Region auf einen US-Endpunkt kann das Versprechen im AVV brechen; siehe ",{"tag":380,"to":457,"children":458},"\u002Fblog\u002Fgdpr-llm-api-eu-data-residency",[459],"DSGVO-Datenresidenz für LLM-APIs",".",{"type":140,"level":141,"id":120,"text":121},{"type":133,"content":463},[464,465,468,469,472],"Ohne Gedächtnis entdeckt jede Anfrage erneut, dass ein Deployment ausgefallen ist, und bezahlt den Timeout. Martin Fowlers Circuit Breaker löst das mit drei Zuständen: geschlossen (Aufrufe gehen durch, Fehler werden gezählt), offen (Aufrufe scheitern sofort, ohne die Abhängigkeit zu berühren) und halboffen (nach einer Wartezeit entscheidet ein Probeaufruf, ob wieder geschlossen wird). LiteLLM liefert eine einfachere Variante pro Deployment: nach ",{"tag":149,"children":466},[467],"allowed_fails"," Fehlern in einer Minute (Standard 3) wird ein Deployment für ",{"tag":149,"children":470},[471],"cooldown_time"," Sekunden (Standard 5) pausiert und der Verkehr geht an die anderen.",{"type":133,"content":474},[475],"Der AWS-Artikel ist bei Breakern vorsichtiger: sie fügen schwer testbares modales Verhalten hinzu und können die Erholung verlangsamen, weshalb AWS lokale Retry-Budgets bevorzugt. Mein Kompromiss sind kurze Cooldowns pro Deployment, ein Retry-Budget pro Client und kein globaler Breaker, der wegen einer lauten Minute ein ganzes Feature abschalten kann.",{"type":140,"level":141,"id":123,"text":124},{"type":133,"content":478},[479,480,484],"Der günstigste 429 ist der, der nie passiert. Bei den meisten Claude-Modellen zählen Cache-Reads nicht zum ITPM, Caching erhöht also den effektiven Durchsatz: Anthropics Beispiel ist ein ITPM-Limit von 2.000.000 mit 80 % Cache-Trefferquote, das 10.000.000 Input-Tokens pro Minute verarbeitet. Das Setup steht in ",{"tag":380,"to":481,"children":482},"\u002Fblog\u002Fllm-cost-latency-prompt-caching-routing",[483],"Prompt-Caching und Modell-Routing",". Weitere Hebel:",{"type":336,"items":486},[487,492,497,510],[488,491],{"tag":340,"children":489},[490],"Workloads trennen."," Anthropic-Workspaces können eigene, niedrigere Limits haben, damit ein Backfill den Chat-Endpunkt nicht aushungert. Getrennte Keys oder Projekte leisten anderswo dasselbe.",[493,496],{"tag":340,"children":494},[495],"Offline-Arbeit von der synchronen API nehmen."," Batch-Endpunkte haben eigene Limits und verbrauchen nicht die Limits der Messages API.",[498,501,502,505,506,509],{"tag":340,"children":499},[500],"Die Header lesen."," Mit ",{"tag":149,"children":503},[504],"anthropic-ratelimit-*-remaining"," und ",{"tag":149,"children":507},[508],"x-ratelimit-remaining-*"," kann sich ein Client selbst drosseln, bevor es der Anbieter tut.",[511,514,515,460],{"tag":340,"children":512},[513],"Schrittweise hochfahren."," Backfills langsam starten, um Beschleunigungslimits zu meiden, und öffentliche Endpunkte vor Missbrauch schützen, siehe ",{"tag":380,"to":516,"children":517},"\u002Fblog\u002Fllm-endpoint-abuse-denial-of-wallet",[518],"Denial of Wallet",{"type":140,"level":141,"id":126,"text":127},{"type":133,"content":521},[522,523,526,527,193,530,505,533,536],"Eine Retry-Policy ohne Timeout ist unvollständig, denn eine hängende Verbindung erzeugt nie einen Fehler, den man wiederholen könnte. AWS empfiehlt, Timeouts aus Latenzperzentilen der Abhängigkeit abzuleiten statt zu raten. Für LLM-Aufrufe heißt das getrennte Budgets für die Zeit bis zum ersten Token und die Gesamtdauer. Anthropic empfiehlt Streaming oder die Batches API für Anfragen, die länger als zehn Minuten laufen können, weil manche Netze inaktive Verbindungen trennen, und die SDKs lehnen nicht gestreamte Anfragen ab, die voraussichtlich ein Zehn-Minuten-Timeout überschreiten. Das AI SDK nimmt ein ",{"tag":149,"children":524},[525],"timeout","-Objekt mit ",{"tag":149,"children":528},[529],"totalMs",{"tag":149,"children":531},[532],"stepMs",{"tag":149,"children":534},[535],"chunkMs",", das genau auf diese Budgets passt.",{"type":133,"content":538},[539,540,543,544,548],"Bei jedem Fehler den ",{"tag":149,"children":541},[542],"request-id","-Header loggen. Liegt ein Vorfall beim Anbieter, fragt dessen Support genau nach dieser ID, und aus einem vagen „die API war langsam“ wird etwas Nachverfolgbares. Retries, Fallbacks und das bedienende Modell in denselben Trace schreiben, wie in ",{"tag":380,"to":545,"children":546},"\u002Fblog\u002Fagent-observability-opentelemetry",[547],"Observability für LLM-Agenten",", dann sieht man hinterher, wie viel eines Vorfalls die Kette abgefangen hat.",{"type":140,"level":141,"id":129,"text":130},{"type":336,"ordered":551,"items":552},true,[553,557,560,563,566,569,572,575,578,581],[554],{"tag":555,"href":39,"children":556},"a",[38],[558],{"tag":555,"href":42,"children":559},[41],[561],{"tag":555,"href":45,"children":562},[44],[564],{"tag":555,"href":48,"children":565},[47],[567],{"tag":555,"href":51,"children":568},[50],[570],{"tag":555,"href":54,"children":571},[53],[573],{"tag":555,"href":57,"children":574},[56],[576],{"tag":555,"href":60,"children":577},[59],[579],{"tag":555,"href":63,"children":580},[62],[582],{"tag":555,"href":66,"children":583},[65],[585,646,702,755],{"slug":586,"published":5,"minutes":587,"category":7,"tags":588,"keywords":594,"about":605,"sources":615,"cover":640,"og":641,"expertise":69,"locales":642,"lang":72,"title":643,"description":644,"coverAlt":645},"prompt-versioning-management",8,[589,590,591,592,593],"Prompt management","Versioning","LLMOps","Evals","Langfuse",[595,596,597,598,599,600,601,602,603,604],"prompt versioning","prompt management","prompt registry","version control for prompts","langfuse prompt management","mlflow prompt registry","prompts in git","openai prompt object deprecation","prompt rollback production","prompt ci evaluation",[606,609,612],{"name":607,"url":608},"Prompt engineering","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FPrompt_engineering",{"name":610,"url":611},"Version control","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FVersion_control",{"name":613,"url":614},"Continuous integration","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FContinuous_integration",[616,619,622,625,628,631,634,637],{"title":617,"url":618},"OpenAI API Docs: Migrate from prompt objects","https:\u002F\u002Fdevelopers.openai.com\u002Fapi\u002Fdocs\u002Fguides\u002Fprompting\u002Fmigrate-from-prompt-object",{"title":620,"url":621},"OpenAI API Docs: Prompt engineering (reusable prompts deprecation note)","https:\u002F\u002Fdevelopers.openai.com\u002Fapi\u002Fdocs\u002Fguides\u002Fprompt-engineering",{"title":623,"url":624},"Langfuse Docs: Prompt version control","https:\u002F\u002Flangfuse.com\u002Fdocs\u002Fprompt-management\u002Ffeatures\u002Fprompt-version-control",{"title":626,"url":627},"Langfuse Docs: Prompt caching in the SDKs","https:\u002F\u002Flangfuse.com\u002Fdocs\u002Fprompt-management\u002Ffeatures\u002Fcaching",{"title":629,"url":630},"Langfuse Docs: Link prompts to traces","https:\u002F\u002Flangfuse.com\u002Fdocs\u002Fprompt-management\u002Ffeatures\u002Flink-to-traces",{"title":632,"url":633},"MLflow Docs: Prompt Registry","https:\u002F\u002Fmlflow.org\u002Fdocs\u002Flatest\u002Fgenai\u002Fprompt-registry\u002F",{"title":635,"url":636},"Promptfoo Docs: GitHub Action","https:\u002F\u002Fwww.promptfoo.dev\u002Fdocs\u002Fintegrations\u002Fgithub-action\u002F",{"title":638,"url":639},"Claude Platform Docs: Prompt caching","https:\u002F\u002Fplatform.claude.com\u002Fdocs\u002Fen\u002Fbuild-with-claude\u002Fprompt-caching","\u002Fimages\u002Fblog\u002Fprompt-versioning-management\u002Fcover.webp","\u002Fimages\u002Fblog\u002Fprompt-versioning-management\u002Fog.jpg",[71,72,73],"Prompt-Versionierung in Produktion: Git, Registries, Labels und Rollbacks","Prompts in Produktion versionieren: was zu einer Version gehört, Git oder Prompt-Registry, Labels und Rollbacks, Eval-Gates in CI und Folgen für Caches.","Fünf aufrechte Karten in einer Reihe, die dritte schwenkt an einem Bogenpfeil zurück, ein Tor vor der letzten.",{"slug":647,"published":5,"minutes":648,"category":7,"tags":649,"keywords":654,"about":665,"sources":675,"cover":696,"og":697,"expertise":69,"locales":698,"lang":72,"title":699,"description":700,"coverAlt":701},"llm-batch-api-offline-workloads",9,[650,651,591,652,653],"Batch API","Cost","Prompt caching","Data pipelines",[655,656,657,658,659,660,661,662,663,664],"llm batch api","anthropic message batches api","openai batch api","gemini batch mode","batch inference llm cost","batch api 50 percent discount","openai flex processing","bedrock batch inference","llm offline processing","batch api prompt caching",[666,669,672],{"name":667,"url":668},"Batch processing","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FBatch_processing",{"name":670,"url":671},"JSON Lines","https:\u002F\u002Fjsonlines.org\u002F",{"name":673,"url":674},"Large language model","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FLarge_language_model",[676,679,681,682,685,688,690,693],{"title":677,"url":678},"Claude Platform Docs: Batch processing","https:\u002F\u002Fplatform.claude.com\u002Fdocs\u002Fen\u002Fbuild-with-claude\u002Fbatch-processing",{"title":680,"url":39},"Claude Platform Docs: Rate limits (Message Batches API)",{"title":638,"url":639},{"title":683,"url":684},"OpenAI API Docs: Batch API","https:\u002F\u002Fdevelopers.openai.com\u002Fapi\u002Fdocs\u002Fguides\u002Fbatch",{"title":686,"url":687},"OpenAI API Docs: Flex processing","https:\u002F\u002Fdevelopers.openai.com\u002Fapi\u002Fdocs\u002Fguides\u002Fflex-processing",{"title":689,"url":45},"OpenAI API Docs: Rate limits (batch queue limits)",{"title":691,"url":692},"Google AI for Developers: Gemini Batch API","https:\u002F\u002Fai.google.dev\u002Fgemini-api\u002Fdocs\u002Fbatch-api",{"title":694,"url":695},"Amazon Bedrock User Guide: Batch inference","https:\u002F\u002Fdocs.aws.amazon.com\u002Fbedrock\u002Flatest\u002Fuserguide\u002Fbatch-inference.html","\u002Fimages\u002Fblog\u002Fllm-batch-api-offline-workloads\u002Fcover.webp","\u002Fimages\u002Fblog\u002Fllm-batch-api-offline-workloads\u002Fog.jpg",[71,72,73],"LLM-Batch-APIs: Inferenz zum halben Preis für Arbeit, die warten kann","Wann sich die Batch-APIs von Anthropic, OpenAI und Gemini lohnen, wie Limits, Zuordnung und Fehler funktionieren und wie sich Rabatte mit Caching addieren.","Eine breite Kiste mit acht kleinen Quadraten, Zulauf von links, ein langer Pfeil kehrt zurück.",{"slug":703,"published":704,"minutes":648,"category":7,"tags":705,"keywords":711,"about":723,"sources":730,"cover":749,"og":750,"expertise":69,"locales":751,"lang":72,"title":752,"description":753,"coverAlt":754},"structured-outputs-json-schema-llm","2026-10-16",[706,707,708,709,710],"Structured outputs","JSON Schema","Constrained decoding","LLM APIs","Validation",[712,713,714,715,716,717,718,719,720,721,722],"structured outputs LLM","JSON schema LLM output","OpenAI structured outputs strict mode","Claude structured outputs","Gemini structured output","constrained decoding","JSON mode vs structured outputs","validate LLM JSON output","Zod structured output","Pydantic LLM output","vLLM structured outputs",[724,727,729],{"name":725,"url":726},"JSON","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FJSON",{"name":707,"url":728},"https:\u002F\u002Fjson-schema.org\u002F",{"name":673,"url":674},[731,734,737,740,743,746],{"title":732,"url":733},"OpenAI API docs: Structured model outputs","https:\u002F\u002Fplatform.openai.com\u002Fdocs\u002Fguides\u002Fstructured-outputs",{"title":735,"url":736},"Claude API docs: Structured outputs","https:\u002F\u002Fplatform.claude.com\u002Fdocs\u002Fen\u002Fbuild-with-claude\u002Fstructured-outputs",{"title":738,"url":739},"Gemini API docs: Structured outputs","https:\u002F\u002Fai.google.dev\u002Fgemini-api\u002Fdocs\u002Fstructured-output",{"title":741,"url":742},"vLLM docs: Structured Outputs","https:\u002F\u002Fdocs.vllm.ai\u002Fen\u002Flatest\u002Ffeatures\u002Fstructured_outputs.html",{"title":744,"url":745},"Tam et al.: Let Me Speak Freely? A Study on the Impact of Format Restrictions on Performance of LLMs (2024)","https:\u002F\u002Farxiv.org\u002Fabs\u002F2408.02442",{"title":747,"url":748},"Geng et al.: JSONSchemaBench: A Rigorous Benchmark of Structured Outputs for Language Models (2025)","https:\u002F\u002Farxiv.org\u002Fabs\u002F2501.10868","\u002Fimages\u002Fblog\u002Fstructured-outputs-json-schema-llm\u002Fcover.webp","\u002Fimages\u002Fblog\u002Fstructured-outputs-json-schema-llm\u002Fog.jpg",[71,72,73],"Structured Outputs mit JSON Schema: was die Garantie abdeckt und was nicht","Wie Structured Outputs und Constrained Decoding bei OpenAI, Claude, Gemini und vLLM funktionieren, welche Schemaregeln zählen und was du validierst.","Ein festes Raster aus vier Fächern, drei Blöcke sitzen darin, einer zu breit schwebt darüber.",{"slug":756,"published":704,"minutes":648,"category":7,"tags":757,"keywords":763,"about":776,"sources":784,"cover":806,"og":807,"expertise":69,"locales":808,"lang":72,"title":809,"description":810,"coverAlt":811},"evaluating-ai-agents-trajectories",[758,759,760,761,762],"Agent evals","Trajectories","Tool calling","pass^k","LLM-as-judge",[764,765,766,767,768,769,770,771,772,773,774,775],"evaluating AI agents","agent trajectory evaluation","agent evals","tool call accuracy","trajectory match evaluator","pass^k metric","tau-bench","LLM as a judge for agents","agent regression testing","outcome vs trajectory evaluation","agentevals","tool correctness metric",[777,780,783],{"name":778,"url":779},"Intelligent agent","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FIntelligent_agent",{"name":781,"url":782},"Software testing","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FSoftware_testing",{"name":673,"url":674},[785,788,791,794,797,800,803],{"title":786,"url":787},"Anthropic: Demystifying evals for AI agents (Jan 2026)","https:\u002F\u002Fwww.anthropic.com\u002Fengineering\u002Fdemystifying-evals-for-ai-agents",{"title":789,"url":790},"Yao et al.: τ-bench: A Benchmark for Tool-Agent-User Interaction in Real-World Domains (2024)","https:\u002F\u002Farxiv.org\u002Fabs\u002F2406.12045",{"title":792,"url":793},"Barres et al.: τ²-Bench: Evaluating Conversational Agents in a Dual-Control Environment (2025)","https:\u002F\u002Farxiv.org\u002Fabs\u002F2506.07982",{"title":795,"url":796},"LangChain: agentevals (GitHub)","https:\u002F\u002Fgithub.com\u002Flangchain-ai\u002Fagentevals",{"title":798,"url":799},"DeepEval docs: Tool Correctness","https:\u002F\u002Fdeepeval.com\u002Fdocs\u002Fmetrics-tool-correctness",{"title":801,"url":802},"Ragas docs: Agentic or tool use metrics","https:\u002F\u002Fdocs.ragas.io\u002Fen\u002Fstable\u002Fconcepts\u002Fmetrics\u002Favailable_metrics\u002Fagents\u002F",{"title":804,"url":805},"OpenAI API docs: Trace grading","https:\u002F\u002Fplatform.openai.com\u002Fdocs\u002Fguides\u002Ftrace-grading","\u002Fimages\u002Fblog\u002Fevaluating-ai-agents-trajectories\u002Fcover.webp","\u002Fimages\u002Fblog\u002Fevaluating-ai-agents-trajectories\u002Fog.jpg",[71,72,73],"KI-Agenten evaluieren: Trajektorien, Ergebnisse und Zuverlässigkeit bewerten","KI-Agenten evaluieren: Ergebnis- und Trajektorie-Grader, Match-Modi, pass^k, isolierte Umgebungen und LLM-Judges, die belastbar sind.","Zwei gepunktete Wege aus Kreisen zwischen zwei Quadraten, eine Klammer umrahmt den gebogenen Weg.",1792222777390]