A motor fallback chain-je négy rétegű, és egy darabig azt hittük, ez bullet-proof. A négy réteg sorrendben: (1) másik provider ugyanazon a modell-családon, (2) másik család a sztenderd provider-en, (3) olcsóbb modell ugyanazon a családon, (4) web-search-augmented végső válasz. Az első három csak akkor lép működésbe, ha az előző réteg explicit error-ral elesik vagy SLO-túllépést mutat 8 másodpercen belül. A negyedik réteg egy degraded mód, ami egy „nem tudtunk válaszolni” + web search snapshotot adott vissza.
Két hónapig hibátlanul futott. Aztán április első hetében egy 18 perces incidenst okozott, amit nem azonnal értettünk.
A nem-nyilvánvaló buktató
A fallback chain deadlock-olhat, ha minden réteg egyszerre „degraded mode”-ban van. Ez nem hipotetikus: április 4-én az OpenAI Realtime API egy regionális outage-en ment keresztül (eu-west-1), miközben az Anthropic Claude egy rate-limit window-t hitelt egy big enterprise tenant heavy load-ja miatt, és az ElevenLabs egy hangminta-feldolgozási lassulást élt át (TTS válaszidő 5x normál). Egy fallback request mindhárom rétegen átment, mindegyik visszadobta („timeout”, „rate-limited”, „degraded”), és a negyedik réteg web-search-augmented response-ja értelmetlen volt, mert a felhasználói kérdés egy belső termékre vonatkozott, amiről a web nem tud semmit.
A result: 18 perc, ami alatt minden olyan kérés, ami a motoron keresztülment és Európán belüli adatközpontba esett, egyetlen választ kapott: „Sajnálom, a kérdésére jelenleg nem tudok válaszolni.” 4 217 kérés, 412 tenant.
A circuit-breaker pattern
A javítás két részből áll. Először: minden fallback rétegnek saját circuit breakere van. Ha egy réteg az utolsó 60 másodpercben 25%-os hibaarány felett van, a circuit nyitva van, és a router KIHAGYJA azt a réteget — egyenesen a következő rétegre megy. A circuit fél nyitva van 60-90 másodperc között (1 trial request fut, ha sikerül, zárva), és teljesen zárva van 90 másodperc után, ha a trial-ek sikeresek.
Másodszor: minden fallback chain-nek van egy globális hard timeout-ja: 12 másodperc. Ha a chain összesített ideje meghaladja a 12 másodpercet, a kérés egy degraded gyorsválaszt kap (egy templatizált „a motor jelenleg túlterhelt, kérjük próbálja újra” üzenetet), és egy chain.exceeded_max_time counter növekszik. Ez nem szép, de meghal a kérés kontrolláltan, nem véletlenül.
A 12 másodperc nem önkényes. A teljes per-request user-türelem-ablak mediánja 28 másodperc (mértük), a 95-percentil 14 másodperc. A 12 másodperc azt biztosítja, hogy a felhasználók 95%-a inkább kap egy „túlterhelt” üzenetet, mint hogy elhagyja az alkalmazást.
Amit még mindig nem tudunk
A chain dynamics előrejelzése. Most reaktívak vagyunk — várjuk, hogy a circuit-breaker tüzeljen. Egy proaktív rendszer (provider health prediction) sokat segítene, de még nem mértük, hogy a provider-health-jelek megbízhatóan előrejelzik-e a chain deadlockot. A következő negyedév kutatás-tárgya. A jelek, amiket már gyűjtünk — provider-oldali latencia-hisztogramok, regionális hibaarány, rate-limit ablak-kihasználtság — feletethetnek egy kis predictort, de még nem találtunk olyan modellt, aminek a precíziója elég magas ahhoz, hogy alapján cselekedjünk (a hamis-pozitív circuit-open események maguk is degradált latencia forrása).
A poszt-incidens dashboard
Az áprilisi incidens egyetlen tartós műterméket szült: egy Grafana board, ami minden provider minden fallback rétegének élő állapotát mutatja régiónként. Zöld csempe = circuit zárva, sárga = félig nyitva trial-lel, piros = nyitva. Egy második sor a gördülő 60 másodperces hibaarányt mutatja rétegenként. Az on-call mérnök első akciója minden voice-vagy-chat alertnél most ennek a boardnak a megnyitása. Az incidens előtt ugyanezek az információk négy különálló dashboardon szétszórva voltak, három különböző tool-ban; a konszolidáció ugyanolyan fontos volt, mint maga a circuit-breaker kód.
Négy hónap üzemelés ezzel a mintával: nulla chain-deadlock incidens. Három majdnem-baj eset, amikor két réteg egyidejűleg degradált és a harmadik elnyelte a terhelést. Egy hamis-pozitív circuit-open (egy provider tranziens 5xx tüskéje, ami egyetlen rossz pod-nak bizonyult, 40 másodperc alatt visszajött) ami kb. 200 EUR felesleges fallback-költséget hozott egy drágább modellre. A 200 EUR hamis-pozitív költséget tisztességes árnak tartjuk a megelőzött incidens-osztályért.