ktg-plugin-marketplace/plugins/ms-ai-architect/skills/ms-ai-engineering/references/api-management/load-balancing-openai-instances.md
Kjell Tore Guttormsen 6a7632146e feat(ms-ai-architect): add plugin to open marketplace (v1.5.0 baseline)
Initial addition of ms-ai-architect plugin to the open-source marketplace.
Private content excluded: orchestrator/ (Linear tooling), docs/utredning/
(client investigation), generated test reports and PDF export script.
skill-gen tooling moved from orchestrator/ to scripts/skill-gen/.

Security scan: WARNING (risk 20/100) — no secrets, no injection found.
False positive fixed: added gitleaks:allow to Python variable reference
in output-validation-grounding-verification.md line 109.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 17:17:17 +02:00

17 KiB

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:

<!-- Policy: Rut til backend pool -->
<set-backend-service backend-id="openai-pool" />

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:

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:

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:

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:

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

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

<policies>
    <inbound>
        <set-backend-service backend-id="openai-pool-priority" />
        <authentication-managed-identity
            resource="https://cognitiveservices.azure.com/" />
    </inbound>
</policies>

RBAC-konfigurasjon:

// 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:

<policies>
    <inbound>
        <set-backend-service backend-id="openai-pool-priority" />

        <!-- Override deployment name basert på backend-region -->
        <choose>
            <when condition="@(context.Backend?.AzureRegion == "norwayeast")">
                <rewrite-uri template="/deployments/gpt-4o/chat/completions" />
            </when>
            <when condition="@(context.Backend?.AzureRegion == "swedencentral")">
                <rewrite-uri template="/deployments/gpt4-turbo/chat/completions" />
            </when>
        </choose>

        <authentication-managed-identity
            resource="https://cognitiveservices.azure.com/" />
    </inbound>
</policies>

Modell-versjonshåndtering

<!-- Sett api-version basert på backend -->
<set-query-parameter name="api-version" exists-action="override">
    <value>2024-10-21</value>
</set-query-parameter>

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:

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:

<choose>
    <when condition="@(context.Deployment.Region == "Norway East")">
        <set-backend-service backend-id="pool-norwayeast" />
    </when>
    <when condition="@(context.Deployment.Region == "Sweden Central")">
        <set-backend-service backend-id="pool-swedencentral" />
    </when>
</choose>

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)
<policies>
    <inbound>
        <set-backend-service backend-id="openai-pool-priority" />
    </inbound>

    <backend>
        <retry condition="@(context.Response.StatusCode == 429)"
               count="3"
               interval="0"
               first-fast-retry="true">
            <set-backend-service backend-id="openai-pool-priority" />
        </retry>
    </backend>
</policies>

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

@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

<outbound>
    <set-header name="X-Backend-Id" exists-action="override">
        <value>@(context.Backend?.Id ?? "unknown")</value>
    </set-header>
    <set-header name="X-Backend-Type" exists-action="override">
        <value>@(context.Backend?.Type ?? "unknown")</value>
    </set-header>
</outbound>

KQL for load balancing-distribusjon

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.