# Circuit Breaker Patterns for AI Models **Last updated:** 2026-02 **Status:** GA **Category:** API Management & AI Gateway --- ## Introduksjon Circuit breaker-mønsteret er en grunnleggende resiliensmekanisme for AI-applikasjoner som kommuniserer med Azure OpenAI og andre LLM-backends. Når en backend-tjeneste blir overbelastet eller utilgjengelig, forhindrer circuit breaker at applikasjonen fortsetter å sende forespørsler som uansett vil feile. I stedet "bryter kretsen" og returnerer en feilmelding umiddelbart, slik at backend-tjenesten får tid til å gjenopprette seg. For Azure AI-tjenester er circuit breaker spesielt viktig fordi Azure OpenAI returnerer 429 (Too Many Requests) med en `Retry-After`-header som kan ha verdier opp til 24 timer. Uten circuit breaker vil applikasjoner fortsette å hamre på en throttlet tjeneste, noe som forverrer situasjonen og kaster bort gateway-ressurser. APIMsintegrerte circuit breaker håndterer dette automatisk ved å respektere `Retry-After`-headeren. I kombinasjon med backend pools og lastbalansering utgjør circuit breaker selve nervesystemet i en intelligent AI-gateway: den detekterer problemer, isolerer feilende backends, ruter trafikk til friske alternativer, og gjenoppretter normal drift automatisk når backend er tilbake. --- ## Circuit Breaker State Machine ### Tre tilstander Circuit breaker opererer som en tilstandsmaskin med tre tilstander: ``` Feil > threshold ┌─────────┐ ───────────────► ┌──────────┐ │ CLOSED │ │ OPEN │ │ (normal)│ ◄────────────── │ (trip) │ └─────────┘ Alle OK i └──────────┘ │ half-open │ │ │ Trip duration │ │ utløpt │ ┌──────────────┐ │ │ │ HALF-OPEN │◄───┘ │ │ (test) │ │ └──────────────┘ │ │ │ Suksess │ Feil ◄──────────────┘───────────► OPEN ``` | Tilstand | Oppførsel | Varighet | |----------|-----------|----------| | **Closed** | Normal drift, alle requests videresendes til backend | Ubegrenset (til feilbetingelse oppstår) | | **Open** | Alle requests avvises umiddelbart med 503 | Trip duration (konfigurerbar, eller fra Retry-After) | | **Half-Open** | Et begrenset antall test-requests sendes til backend | Til nok suksesser ELLER ny feil | ### APIM-spesifikk oppførsel APIMcircuit breaker har noen viktige forskjeller fra den generelle circuit breaker-mønsteret: | Egenskap | APIM Circuit Breaker | |----------|---------------------| | **Konfigurasjons-scope** | Per backend (ikke per API eller policy) | | **Antall regler** | Kun én regel per backend (p.t.) | | **Synkronisering** | Ingen mellom gateway-instanser (approksimasjon) | | **Retry-After respekt** | Ja, dynamisk trip duration basert på backend-respons | | **Støttede tiers** | Alle unntatt Consumption | | **Respons ved Open** | 503 Service Unavailable | --- ## Konfigurasjon ### Grunnleggende circuit breaker for Azure OpenAI ```bicep resource openaiBackend 'Microsoft.ApiManagement/service/backends@2023-09-01-preview' = { parent: apim name: 'openai-norwayeast' properties: { url: 'https://aoai-norwayeast.openai.azure.com/openai' protocol: 'http' circuitBreaker: { rules: [ { name: 'ai-resilience-rule' failureCondition: { count: 3 interval: 'PT1M' statusCodeRanges: [ { min: 429, max: 429 } { min: 500, max: 599 } ] } tripDuration: 'PT10S' acceptRetryAfter: true } ] } } } ``` ### Attributter forklart | Attributt | Type | Beskrivelse | Anbefalt verdi for AI | |-----------|------|-------------|----------------------| | `failureCondition.count` | int | Antall feil som trigger trip | 3-5 | | `failureCondition.interval` | duration | Tidsvindu for feil-telling | PT1M (1 minutt) | | `failureCondition.statusCodeRanges` | array | HTTP-koder som teller som feil | 429 + 500-599 | | `tripDuration` | duration | Hvor lenge circuit er åpent | PT10S - PT1M | | `acceptRetryAfter` | bool | Bruk Retry-After header som trip duration | **true** (alltid for AI) | ### Prosentbasert vs. count-basert triggering APIM støtter to modeller for feil-deteksjon: **Count-basert (anbefalt for AI):** ```json { "failureCondition": { "count": 3, "interval": "PT1M", "statusCodeRanges": [{"min": 429, "max": 429}] } } ``` Trigger: 3 eller flere 429-responser innen 1 minutt. **Prosentbasert:** ```json { "failureCondition": { "percentage": 50, "interval": "PT1M", "statusCodeRanges": [{"min": 429, "max": 429}] } } ``` Trigger: 50% eller mer av requests feiler innen 1 minutt. **Anbefaling:** Count-basert er mer forutsigbar for AI-workloads. Prosentbasert kan gi falske positiver ved lav trafikk (2 av 3 requests feiler = 66%). --- ## Failure Threshold Tuning ### Faktorene som påvirker threshold | Faktor | Lav threshold (1-2) | Høy threshold (5-10) | |--------|---------------------|---------------------| | **Reaksjonstid** | Rask, reagerer umiddelbart | Tregere, tolererer noen feil | | **Falske positiver** | Høy risiko | Lav risiko | | **Backend-beskyttelse** | Sterk, minimal ekstra belastning | Svakere, flere feil-requests | | **Anbefalt for** | Kritiske, kapasitetsbegrensede backends | Robuste backends med transiente feil | ### Anbefalte innstillinger per scenario | Scenario | count | interval | tripDuration | acceptRetryAfter | |----------|-------|----------|--------------|-----------------| | **PTU-instans (high priority)** | 3 | PT1M | PT10S | true | | **PAYGO-instans (fallback)** | 5 | PT2M | PT30S | true | | **Dev/test** | 2 | PT30S | PT5S | true | | **Business-critical** | 3 | PT1M | PT10S | true | | **Batch processing** | 10 | PT5M | PT1M | true | ### Dynamisk trip duration med Retry-After Når `acceptRetryAfter: true` er satt, overstyrer Azure OpenAIs `Retry-After`-header den konfigurerte `tripDuration`: ``` Scenario: OpenAI returnerer 429 med Retry-After: 30 → Circuit breaker åpner i 30 sekunder (ikke konfiguert tripDuration) → Etter 30 sekunder: half-open → test request → Suksess: circuit lukkes → Feil: circuit åpner igjen med ny Retry-After Scenario: OpenAI returnerer 429 med Retry-After: 86400 (1 dag!) → Circuit breaker åpner i 24 timer → All trafikk rutes til andre backends i poolen ``` > **Viktig advarsel:** Azure OpenAI kan returnere Retry-After verdier opp til 1 dag (86400 sekunder). Med `acceptRetryAfter: true` vil dette bety at backend er utilgjengelig i 24 timer. Sørg for at backend-poolen har nok kapasitet i andre backends til å håndtere dette. --- ## Fallback-policies ### Mønster 1: Backend Pool med automatisk failover Den enkleste og mest robuste tilnærmingen: ```xml ``` Når circuit breaker utløses på Priority 1-backends, ruter APIM automatisk til Priority 2, osv. ### Mønster 2: Retry med backend-bytte Eksplisitt retry-logikk som bytter backend ved 429: ```xml ``` **Viktig:** `interval="0"` betyr umiddelbar retry til neste backend, IKKE ventetid. Server-side retries bør aldri ha delay — det holder opp klienten og bruker gateway-ressurser. ### Mønster 3: Graceful Degradation med cache-fallback ```xml 60 @{ return new JObject( new JProperty("error", new JObject( new JProperty("code", "service_unavailable"), new JProperty("message", "AI-tjenesten er midlertidig utilgjengelig. Prøv igjen om 60 sekunder."), new JProperty("type", "circuit_breaker_open") )) ).ToString(); } ``` ### Mønster 4: Fallback til enklere modell ```xml ``` --- ## Recovery-mekanismer ### Automatisk recovery Circuit breaker håndterer recovery automatisk: ``` 1. Trip: Circuit åpner (503 til klienter) 2. Wait: tripDuration utløper (eller Retry-After) 3. Half-Open: Test-request sendes til backend 4. Success: Circuit lukkes, normal drift gjenopptas 5. Failure: Circuit åpner igjen, ny tripDuration starter ``` ### Recovery-timing | Kilde | Prioritet | Typisk verdi | |-------|-----------|--------------| | `Retry-After` header (når `acceptRetryAfter: true`) | Høyest | 1-86400 sekunder | | Konfigurert `tripDuration` | Fallback | PT10S - PT1M | | Default (uten konfigurasjon) | Lavest | PT1M | ### Overvåking av circuit breaker-tilstand ```xml @{ var backendId = context.Backend?.Id ?? "unknown"; var statusCode = context.Response.StatusCode; return $"Backend: {backendId}, Status: {statusCode}"; } ``` **KQL for circuit breaker-hendelser:** ```kusto ApiManagementGatewayLogs | where ResponseCode == 503 | extend backendId = tostring(parse_json(BackendResponseBody).backendId) | summarize CircuitBreakerTrips = count() by backendId, bin(TimeGenerated, 5m) | render timechart ``` --- ## Timeout-konfigurasjon ### Forward-request timeout Kontroller hvor lenge APIM venter på backend-respons: ```xml ``` **Anbefalte timeouts for AI-workloads:** | Operasjon | Anbefalt timeout | Begrunnelse | |-----------|------------------|-------------| | Chat Completion (standard) | 60-120 sek | GPT-4o kan bruke tid på komplekse prompts | | Chat Completion (streaming) | 120-180 sek | Streaming starter raskt, men kan vare lenge | | Embeddings | 30-60 sek | Raskere operasjon, typisk < 10 sek | | Image Generation (DALL-E) | 120-180 sek | Bildegenerering er CPU-intensivt | | Assistants API | 180-300 sek | Multi-step agent workflows | | Batch API | 300-600 sek | Store batch-operasjoner | ### Timeout + Circuit Breaker interaksjon ``` Timeout utløper (120 sek) → APIM registrerer det som feil → Teller mot circuit breaker threshold → Etter N timeouts → Circuit breaker trip → Backend fjernes fra pool → Trafikk til alternativer ``` > **Best practice:** Sett timeout lavere enn det du tror er nødvendig. Bedre å få rask feil og retry til annen backend enn å vente 120 sekunder på en hengende request. --- ## Avanserte mønstre ### Mønster: Cascading Circuit Breakers For multi-tier arkitekturer der APIM ruter til mellomtjenester som igjen kaller Azure OpenAI: ``` Client → APIM [CB-1] → Custom Service [CB-2] → Azure OpenAI ``` ```bicep // CB-1: APIM → Custom Service resource customServiceBackend 'Microsoft.ApiManagement/service/backends@2023-09-01-preview' = { properties: { circuitBreaker: { rules: [{ failureCondition: { count: 5 interval: 'PT2M' statusCodeRanges: [ { min: 502, max: 504 } ] } tripDuration: 'PT30S' }] } } } ``` Applikasjons-nivå CB-2 implementeres med Polly (.NET), resilience4j (Java), eller tilsvarende. ### Mønster: Health Endpoint Monitoring Kombiner circuit breaker med aktiv health checking: ```xml @("https://aoai-norwayeast.openai.azure.com/openai/models?api-version=2024-10-21") GET ``` > **Merk:** Health endpoint monitoring legger til latens og backend-belastning. Bruk det kun for scenarier der circuit breaker alene ikke gir rask nok failover. --- ## Anti-mønstre | Anti-mønster | Problem | Løsning | |--------------|---------|---------| | **Ingen circuit breaker** | Backend overbelastes, cascading failure | Aktiver circuit breaker på alle AI-backends | | **For lav threshold (count=1)** | Falske positiver ved transiente feil | Bruk count=3-5 for produksjon | | **For lang tripDuration** | Backend er unødvendig utilgjengelig | Bruk `acceptRetryAfter: true` | | **Ignorere Retry-After** | Hammer backend som eksplisitt ber om pause | Sett `acceptRetryAfter: true` alltid | | **Server-side delay** | Retry med sleep/delay holder opp klienter | Bruk `interval="0"` med backend pool failover | | **Timeout for lang** | Gateway-ressurser brukt opp på hengende requests | Sett realistiske timeouts per operasjonstype | | **Mangle monitoring** | Ingen innsikt i circuit breaker-oppførsel | Emit metrikk + KQL dashboards | --- ## Komplett resiliens-policy ```xml 60 {"error":{"code":"all_backends_unavailable","message":"Alle AI-backends er midlertidig utilgjengelige"}} ``` --- ## For Cosmo - Circuit breaker er obligatorisk for alle Azure OpenAI backends i produksjon -- uten det risikerer du cascading failures og bortkastet gateway-kapasitet mot throttlede backends. - Sett ALLTID `acceptRetryAfter: true` for Azure OpenAI backends. Azure OpenAI returnerer presise Retry-After verdier som gir optimal recovery-timing. Uten dette bruker du den statiske tripDuration som kan være for kort eller for lang. - Anbefalt baseline: `count: 3`, `interval: PT1M`, `tripDuration: PT10S`, `acceptRetryAfter: true`. Juster count opp for PAYGO-backends med mer toleranse. - Kombiner circuit breaker med backend pools for automatisk failover: når PTU-backend tripper, ruter APIM automatisk til PAYGO-backends uten klient-endringer. - Advarsler: Azure OpenAI kan returnere Retry-After opp til 86400 sekunder (1 dag). Sørg for at arkitekturen har nok alternative backends til å håndtere langvarige circuit breaks.