# Load Balancing Across Azure OpenAI Instances **Last updated:** 2026-02 **Status:** GA **Category:** API Management & AI Gateway --- ## Introduksjon Lastbalansering på tvers av flere Azure OpenAI-instanser er en kritisk kapabilitet for enterprise AI-arkitekturer. Azure OpenAI har begrensninger på tokens per minutt (TPM) og requests per minutt (RPM) per deployment, og én enkelt instans vil sjelden dekke behovene til en hel organisasjon. Ved å distribuere trafikk over flere instanser -- gjerne i ulike regioner -- kan organisasjoner øke total kapasitet, forbedre tilgjengelighet og optimalisere kostnader. Azure API Management (APIM) tilbyr innebygd backend pool-funksjonalitet som gjør dette uten egenutviklet kode. Backend pools støtter round-robin, weighted, priority-basert og session-aware lastbalansering, kombinert med circuit breaker for automatisk failover. For norsk offentlig sektor er dette spesielt relevant: flere etater kan dele infrastruktur, mens Provisioned Throughput Units (PTU) prioriteres for å maksimere investert kapasitet. Det er viktig å forstå at APIM-lastbalansering er approksimasjon: ulike gateway-instanser synkroniserer ikke state seg imellom. Dette betyr at vektede fordelinger er omtrentlige, ikke eksakte. For de fleste AI-brukstilfeller er dette akseptabelt, da Azure OpenAI selv håndterer throttling med 429-responser og Retry-After headers. --- ## Backend Pool-konsepter ### Hva er en backend pool? En backend pool i APIM er en samling av backend-tjenester som gatewayen behandler som én logisk enhet for lastbalansering. For Azure OpenAI betyr dette at flere OpenAI-instanser (potensielt i ulike regioner, med ulike deployment-typer) grupperes bak ett endepunkt. | Egenskap | Verdi | |----------|-------| | Maks backends per pool | 30 | | Synkronisering mellom gateway-instanser | Nei (approksimasjon) | | Session awareness | Ja (cookie-basert) | | Health checking | Via circuit breaker | | Deployment-modell | Bicep, ARM, REST API, Portal | ### Backend-registrering Hver backend i poolen registreres med URL, autentisering og valgfrie metadata: ```xml ``` --- ## Load Balancing-strategier ### Strategi 1: Round-Robin Fordeler requests jevnt mellom alle backends i poolen. ``` Request 1 → Backend A (Norway East) Request 2 → Backend B (Sweden Central) Request 3 → Backend C (West Europe) Request 4 → Backend A (Norway East) ← syklusen gjentas ``` **Bruk når:** - Alle instanser har lik kapasitet (samme TPM-allokering) - Ingen preferanse for spesifikke regioner - Enkel konfigurasjon er prioritert **Bicep:** ```bicep resource backendPool 'Microsoft.ApiManagement/service/backends@2023-09-01-preview' = { parent: apim name: 'openai-pool' properties: { type: 'Pool' pool: { services: [ { id: '/backends/openai-norwayeast' } { id: '/backends/openai-swedencentral' } { id: '/backends/openai-westeurope' } ] } } } ``` ### Strategi 2: Weighted (vektet) Fordeler requests basert på tildelte vekter. Nyttig når backends har ulik kapasitet. ``` Vekter: A=3, B=2, C=1 (totalt 6) → A mottar ~50% av trafikk → B mottar ~33% av trafikk → C mottar ~17% av trafikk ``` **Bruk når:** - Backends har ulik TPM-allokering - Blue-green deployment med gradvis trafikkskift - Ulike pricing-modeller (PTU vs. pay-as-you-go) **Bicep:** ```bicep resource backendPool 'Microsoft.ApiManagement/service/backends@2023-09-01-preview' = { parent: apim name: 'openai-pool-weighted' properties: { type: 'Pool' pool: { services: [ { id: '/backends/openai-norwayeast-ptu' weight: 5 priority: 1 } { id: '/backends/openai-swedencentral-paygo' weight: 3 priority: 1 } { id: '/backends/openai-westeurope-paygo' weight: 2 priority: 1 } ] } } } ``` ### Strategi 3: Priority-Based (anbefalt for AI) Organiserer backends i prioritetsgrupper. Lavere prioritetsnummer = høyere prioritet. Backends i lavere prioritetsgrupper brukes kun når alle backends i høyere grupper er utilgjengelige (circuit breaker utløst). ``` Priority 1: PTU-instanser (fast pris, utnytt først) ├── openai-norwayeast-ptu (weight: 3) └── openai-swedencentral-ptu (weight: 2) Priority 2: Pay-as-you-go fallback ├── openai-westeurope-paygo (weight: 1) └── openai-eastus-paygo (weight: 1) ``` **Typisk scenario for norsk offentlig sektor:** | Prioritet | Deployment-type | Region | Begrunnelse | |-----------|-----------------|--------|-------------| | 1 | PTU | Norway East | Datasuverenitet + fast pris, bruk først | | 1 | PTU | Sweden Central | Nær-region redundans | | 2 | Pay-as-you-go | West Europe | Spillover ved høy last | | 3 | Pay-as-you-go | East US | Nødfallback ved regional utfall | **Bicep:** ```bicep resource backendPool 'Microsoft.ApiManagement/service/backends@2023-09-01-preview' = { parent: apim name: 'openai-pool-priority' properties: { type: 'Pool' pool: { services: [ { id: '/backends/openai-norwayeast-ptu' weight: 3 priority: 1 } { id: '/backends/openai-swedencentral-ptu' weight: 2 priority: 1 } { id: '/backends/openai-westeurope-paygo' weight: 1 priority: 2 } { id: '/backends/openai-eastus-paygo' weight: 1 priority: 3 } ] } } } ``` ### Strategi 4: Session-Aware Sikrer at alle requests fra samme bruker-sesjon rutes til samme backend. Kritisk for Azure OpenAI Assistants API der thread state er bundet til en spesifikk instans. ``` Sesjon 1: Bruker A ──cookie──► Backend A (alle requests i sesjonen) Sesjon 2: Bruker B ──cookie──► Backend B (alle requests i sesjonen) Sesjon 3: Bruker C ──cookie──► Backend A (ny sesjon, tilfeldig valgt) ``` **Bruk når:** - Assistants API (thread state) - Chat-applikasjoner med stateful backends - Når backend cacher bruker-kontekst **Bicep:** ```bicep resource backendPool 'Microsoft.ApiManagement/service/backends@2023-09-01-preview' = { parent: apim name: 'openai-pool-session' properties: { type: 'Pool' pool: { services: [ { id: '/backends/openai-norwayeast' weight: 1 priority: 1 } { id: '/backends/openai-swedencentral' weight: 1 priority: 1 } ] sessionAffinity: { type: 'Cookie' cookieName: 'apim-session-id' } } } } ``` **Cookie-håndtering for klienter:** Klienter MÅ lagre `Set-Cookie`-headeren fra APIM og sende den tilbake i påfølgende requests for å opprettholde sesjonsaffinitet. --- ## Individual Backend-konfigurasjon ### Registrere en Azure OpenAI backend ```bicep resource openaiBackend 'Microsoft.ApiManagement/service/backends@2023-09-01-preview' = { parent: apim name: 'openai-norwayeast-ptu' properties: { url: 'https://aoai-norwayeast.openai.azure.com/openai' protocol: 'http' description: 'Azure OpenAI PTU deployment i Norway East' circuitBreaker: { rules: [ { name: 'openai-circuit-breaker' failureCondition: { count: 3 interval: 'PT1M' statusCodeRanges: [ { min: 429, max: 429 } { min: 500, max: 599 } ] } tripDuration: 'PT10S' acceptRetryAfter: true } ] } } } ``` ### Autentisering via Managed Identity ```xml ``` **RBAC-konfigurasjon:** ```bicep // Grant Cognitive Services User role to APIM managed identity resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { scope: openaiResource name: guid(apim.id, openaiResource.id, 'cognitive-services-user') properties: { roleDefinitionId: subscriptionResourceId( 'Microsoft.Authorization/roleDefinitions', 'a97b65f3-24c7-4388-baec-2e87135dc908' // Cognitive Services User ) principalId: apim.identity.principalId principalType: 'ServicePrincipal' } } ``` --- ## Deployment Slot Selection ### Routing til ulike modell-deployments Når backends har ulike deployment-navn (f.eks. `gpt-4o` i en region, `gpt4-turbo` i en annen), kan APIM-policies transformere URL-en: ```xml ``` ### Modell-versjonshåndtering ```xml 2024-10-21 ``` --- ## Regional Distribution ### Topologi 1: Single-Region APIM, Multi-Region Backends ``` APIM (Norway East) │ ┌────────┼────────┐ ▼ ▼ ▼ OpenAI OpenAI OpenAI (Norway East) (Sweden C.) (West EU) Priority 1 Priority 1 Priority 2 ``` **Fordeler:** Enkel arkitektur, ett kontrollpunkt **Ulemper:** APIM er single point of failure, cross-region latens ### Topologi 2: Multi-Region APIM, Regional Backends ``` Client → DNS (latency-based routing) │ ┌────────┴────────┐ ▼ ▼ APIM Gateway APIM Gateway (Norway East) (Sweden Central) │ │ ▼ ▼ OpenAI OpenAI (Norway East) (Sweden Central) ``` **Fordeler:** Ingen regional single point of failure, lav latens **Ulemper:** Krever APIM Premium, dyrere **Bicep for multi-region APIM:** ```bicep resource apim 'Microsoft.ApiManagement/service@2023-09-01-preview' = { name: 'apim-ai-gateway' location: 'norwayeast' sku: { name: 'Premium' capacity: 1 } properties: { additionalLocations: [ { location: 'swedencentral' sku: { name: 'Premium' capacity: 1 } } ] } } ``` ### Topologi 3: Active-Active med Active-Passive Backends Kombinerer regional redundans med kostnadsoptimalisering: ``` APIM Gateway (Norway East) ├── Active: OpenAI PTU (Norway East) Priority 1 ├── Passive: OpenAI PAYGO (Norway East) Priority 2 └── Cross: OpenAI PAYGO (Sweden C.) Priority 3 (kun ved regional feil) APIM Gateway (Sweden Central) ├── Active: OpenAI PTU (Sweden C.) Priority 1 ├── Passive: OpenAI PAYGO (Sweden C.) Priority 2 └── Cross: OpenAI PAYGO (Norway East) Priority 3 ``` **Regional policy routing:** ```xml ``` --- ## Throttling og Retry-håndtering ### Smart Load Balancing Når en backend returnerer 429 (Too Many Requests), skal gatewayen: 1. Lese `Retry-After`-headeren 2. Markere backend som utilgjengelig via circuit breaker 3. Umiddelbart retry til neste tilgjengelige backend i poolen 4. IKKE vente (ingen delay mellom retries til ulike backends) ```xml ``` ### PTU + PAYGO Spillover-mønster Det mest vanlige mønsteret for kostnadsoptimalisering: ``` Normal trafikk: All trafikk → PTU (Priority 1, fast pris) Ved throttling (PTU kapasitet brukt opp): Circuit breaker utløst på PTU Trafikk → PAYGO (Priority 2, pay-per-token) Etter PTU recovery: Circuit breaker reset Trafikk → PTU (Priority 1, tilbake til fast pris) ``` | Fase | Backend | Kostnad | Latens | |------|---------|---------|--------| | Normal | PTU | Fast (forutsigbar) | Lav (garantert) | | Spillover | PAYGO | Variabel (høyere) | Variabel | | Recovery | PTU | Fast | Lav | --- ## Komplett Bicep-eksempel ```bicep @description('Komplett AI Gateway med priority-based load balancing') param location string = 'norwayeast' param environment string = 'prod' // Azure OpenAI instances resource aoaiNorway 'Microsoft.CognitiveServices/accounts@2024-10-01' existing = { name: 'aoai-norwayeast-${environment}' } resource aoaiSweden 'Microsoft.CognitiveServices/accounts@2024-10-01' existing = { name: 'aoai-swedencentral-${environment}' } // APIM Instance resource apim 'Microsoft.ApiManagement/service@2023-09-01-preview' = { name: 'apim-ai-gw-${environment}' location: location sku: { name: 'StandardV2' capacity: 1 } identity: { type: 'SystemAssigned' } properties: { publisherEmail: 'ai-team@example.no' publisherName: 'AI Gateway' } } // Backend: Norway East PTU resource backendNorwayPTU 'Microsoft.ApiManagement/service/backends@2023-09-01-preview' = { parent: apim name: 'openai-norwayeast-ptu' properties: { url: '${aoaiNorway.properties.endpoint}openai' protocol: 'http' circuitBreaker: { rules: [ { name: 'throttle-protection' failureCondition: { count: 3 interval: 'PT1M' statusCodeRanges: [ { min: 429, max: 429 } { min: 500, max: 599 } ] } tripDuration: 'PT10S' acceptRetryAfter: true } ] } } } // Backend: Sweden Central PAYGO resource backendSwedenPAYGO 'Microsoft.ApiManagement/service/backends@2023-09-01-preview' = { parent: apim name: 'openai-swedencentral-paygo' properties: { url: '${aoaiSweden.properties.endpoint}openai' protocol: 'http' circuitBreaker: { rules: [ { name: 'throttle-protection' failureCondition: { count: 3 interval: 'PT1M' statusCodeRanges: [ { min: 429, max: 429 } { min: 500, max: 599 } ] } tripDuration: 'PT10S' acceptRetryAfter: true } ] } } } // Backend Pool with priority-based routing resource backendPool 'Microsoft.ApiManagement/service/backends@2023-09-01-preview' = { parent: apim name: 'openai-pool' properties: { type: 'Pool' pool: { services: [ { id: '/backends/${backendNorwayPTU.name}' weight: 3 priority: 1 } { id: '/backends/${backendSwedenPAYGO.name}' weight: 1 priority: 2 } ] } } } ``` --- ## Overvåking og feilsøking ### Identifisere hvilken backend som serverte request ```xml @(context.Backend?.Id ?? "unknown") @(context.Backend?.Type ?? "unknown") ``` ### KQL for load balancing-distribusjon ```kusto ApiManagementGatewayLogs | where OperationId == "ChatCompletions_Create" | extend backendUrl = tostring(BackendUrl) | summarize RequestCount = count() by backendUrl, bin(TimeGenerated, 1h) | render columnchart ``` --- ## For Cosmo - Priority-based load balancing med PTU som Priority 1 og PAYGO som Priority 2 er det anbefalte mønsteret for enterprise AI-arkitekturer -- det maksimerer utnyttelsen av forhåndskjøpt kapasitet og faller automatisk tilbake til pay-per-use ved behov. - Backend pools er approksimerte: ulike gateway-instanser synkroniserer ikke, så vektede fordelinger er omtrentlige. For AI-workloads er dette akseptabelt fordi Azure OpenAI selv håndterer throttling med 429/Retry-After. - Session awareness er kritisk for Assistants API og chat-applikasjoner med stateful backends -- aktiver dette med cookie-basert sesjonsaffinitet i pool-konfigurasjonen. - For norsk offentlig sektor med datasuverenitetskrav: prioriter Norway East og Sweden Central, bruk private endpoints, og vurder om cross-region failover til EU-regioner er akseptabelt under gjeldende regelverk. - Kombiner alltid backend pools med circuit breaker (inkludert `acceptRetryAfter: true`) for intelligent failover ved 429-responser fra Azure OpenAI.