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>
16 KiB
Token-Based Rate Limiting & Quota Policies
Last updated: 2026-02 Status: GA Category: API Management & AI Gateway
Introduksjon
Token-basert rate limiting er den viktigste mekanismen for å kontrollere forbruk av AI-tjenester i Azure API Management. I motsetning til tradisjonell request-basert throttling, teller APIM faktisk antall tokens som konsumeres av hver LLM-forespørsel og håndhever grenser basert på dette. Dette er essensielt for norsk offentlig sektor der flere etater og prosjekter deler Azure OpenAI-ressurser og trenger presis kostnadskontroll.
APIM tilbyr to parallelle sett med token-policies: ett spesifikt for Azure OpenAI (azure-openai-token-limit) og ett generelt for alle LLM-er (llm-token-limit). Begge fungerer likt, men det generelle settet støtter også tredjeparts LLM-endepunkter som er kompatible med OpenAI API-formatet. For de fleste scenarier anbefales llm-token-limit da det gir størst fleksibilitet.
I tillegg til tokens per minutt (TPM) rate limits, støtter APIM token-kvoter over lengre perioder (time, dag, uke, måned, år). Kombinasjonen av rate limits og kvoter gir finkornet kontroll: rate limits beskytter mot plutselige spikes, mens kvoter sikrer rettferdig fordeling over tid.
Token-telling i APIM
Hvordan APIM teller tokens
APIM bruker to metoder for token-telling:
| Metode | Tidspunkt | Nøyaktighet | Konfigurasjon |
|---|---|---|---|
| Estimert (prompt) | Før request sendes til backend | Omtrentlig, basert på tegnantall | estimate-prompt-tokens="true" |
| Faktisk (completion) | Etter respons fra backend | Eksakt, fra usage-feltet i respons |
Alltid aktiv for completions |
Estimering av prompt tokens:
Når estimate-prompt-tokens="true" er satt, beregner APIM et estimat av prompt-tokens basert på innholdet i forespørselen. Dette muliggjør pre-validering: hvis estimatet allerede overskrider kvoten, avvises forespørselen umiddelbart uten å bruke backend-ressurser.
Token-estimat = f(antall tegn i prompt, modelltype)
Viktig: Token-estimatet er en tilnærming. Det faktiske tokenforbruket kan avvike, spesielt for ikke-engelske tekster (norsk bruker typisk 20-40% flere tokens enn engelsk for tilsvarende tekst).
Token-flyt i APIM
1. Request mottas av APIM gateway
2. IF estimate-prompt-tokens=true:
Estimer prompt tokens
IF estimat > gjenstående kvote:
RETURNER 429 umiddelbart (ingen backend-kall)
3. Send request til Azure OpenAI backend
4. Motta respons med usage-data:
{
"usage": {
"prompt_tokens": 127,
"completion_tokens": 350,
"total_tokens": 477
}
}
5. Oppdater token-teller med faktiske verdier
6. Emit metrikk til Application Insights
Policy-referanse
llm-token-limit (anbefalt for nye implementasjoner)
<llm-token-limit
counter-key="@(context.Subscription.Id)"
tokens-per-minute="50000"
token-quota="1000000"
token-quota-period="monthly"
estimate-prompt-tokens="true"
remaining-tokens-variable-name="remainingTokens"
remaining-token-quota-variable-name="remainingQuota"
tokens-consumed-variable-name="tokensConsumed">
</llm-token-limit>
Attributter:
| Attributt | Påkrevd | Beskrivelse | Eksempel |
|---|---|---|---|
counter-key |
Ja | Nøkkel for å identifisere konsumenten | @(context.Subscription.Id) |
tokens-per-minute |
Ja | Maks tokens per minutt (TPM) | 50000 |
token-quota |
Nei | Total tokenkvote for perioden | 1000000 |
token-quota-period |
Nei | Kvoteperiode | hourly, daily, weekly, monthly, yearly |
estimate-prompt-tokens |
Nei | Pre-estimer prompt tokens | true / false |
remaining-tokens-variable-name |
Nei | Variabel for gjenstående TPM | remainingTokens |
remaining-token-quota-variable-name |
Nei | Variabel for gjenstående kvote | remainingQuota |
tokens-consumed-variable-name |
Nei | Variabel for brukte tokens | tokensConsumed |
retry-after-variable-name |
Nei | Variabel for retry-after sekunder | retryAfter |
azure-openai-token-limit (Azure OpenAI-spesifikk)
<azure-openai-token-limit
counter-key="@(context.Subscription.Id)"
tokens-per-minute="50000"
estimate-prompt-tokens="true"
remaining-tokens-variable-name="remainingTokens">
</azure-openai-token-limit>
Merk:
azure-openai-token-limitstøtter kun TPM rate limiting, ikke token-kvoter over lengre perioder. Brukllm-token-limitfor full kvotestøtte.
Counter-key-strategier
Valg av counter-key bestemmer granulariteten av rate limiting:
Strategi 1: Per subscription (standard)
<llm-token-limit
counter-key="@(context.Subscription.Id)"
tokens-per-minute="50000" />
Bruk: Standard for de fleste scenarier. Hvert team/prosjekt får egen APIM subscription med dedikert kvote.
Strategi 2: Per IP-adresse
<llm-token-limit
counter-key="@(context.Request.IpAddress)"
tokens-per-minute="10000" />
Bruk: Beskyttelse mot individuelle klienter som overforbruker. Nyttig for interne applikasjoner.
Strategi 3: Per avdeling/etat (custom header)
<llm-token-limit
counter-key="@(context.Request.Headers.GetValueOrDefault("x-etat-id", "default"))"
tokens-per-minute="100000"
token-quota="5000000"
token-quota-period="monthly" />
Bruk: Offentlig sektor der flere etater deler infrastruktur. Krever at klienter sender header.
Strategi 4: Per bruker (JWT claim)
<llm-token-limit
counter-key="@(context.Request.Headers.GetValueOrDefault("Authorization", "").AsJwt()?.Claims["oid"]?.FirstOrDefault() ?? "anonymous")"
tokens-per-minute="5000" />
Bruk: Individuell brukerbegrensning. Krever JWT-token med brukeridentitet.
Strategi 5: Kombinert (subscription + bruker)
<llm-token-limit
counter-key="@(context.Subscription.Id + "-" + context.Request.Headers.GetValueOrDefault("x-user-id", "shared"))"
tokens-per-minute="5000" />
Bruk: Finkornet kontroll der hvert team har en total kvote, men individuelle brukere innen teamet også begrenses.
Rate Limit-algoritmer
Classic tiers: Sliding Window
I Classic tiers (Developer, Basic, Standard, Premium) bruker APIM en sliding window-algoritme:
Tidslinje:
[────────── 60 sek vindu ──────────]
^-- request evalueres her
Tokens brukt i vinduet: 45 000 av 50 000 TPM
Ny request med estimert 6 000 tokens → AVVIST (429)
Ny request med estimert 4 000 tokens → GODKJENT
Egenskaper:
- Jevn fordeling over tid
- Kan gi uventede 429-svar ved burst-trafikk
- Teller akkumuleres over glidende 60-sekunders vindu
V2 tiers: Token Bucket
V2 tiers (Basic v2, Standard v2, Premium v2) bruker en token bucket-algoritme:
Bucket-kapasitet: 50 000 tokens
Refill rate: 50 000 tokens / 60 sek = 833 tokens/sek
Tidspunkt 0: Bucket = 50 000 (full)
Request A: -10 000 → Bucket = 40 000
Request B: -15 000 → Bucket = 25 000
... 10 sek ...
Refill: +8 330 → Bucket = 33 330
Request C: -35 000 → AVVIST (overstiger bucket)
Egenskaper:
- Tillater korte bursts opp til bucket-kapasiteten
- Jevnere throttling-opplevelse
- Mer effektiv for ujevn trafikk (typisk for AI-workloads)
Kvoter over lengre perioder
Kvote vs. Rate Limit
| Egenskap | Rate Limit (TPM) | Kvote |
|---|---|---|
| Tidshorisont | Per minutt | Time, dag, uke, måned, år |
| Formål | Beskytt mot spikes | Rettferdig fordeling over tid |
| Counter scope | Per gateway-instans (regional) | Globalt (på tvers av regioner) |
| HTTP-kode ved overskridelse | 429 Too Many Requests | 403 Forbidden |
| Retry-After header | Ja | Ja |
Eksempel: Månedlig kvote med daglig rate limit
<policies>
<inbound>
<!-- Rate limit: 50 000 TPM -->
<llm-token-limit
counter-key="@(context.Subscription.Id)"
tokens-per-minute="50000"
estimate-prompt-tokens="true" />
<!-- Kvote: 2 000 000 tokens per måned -->
<llm-token-limit
counter-key="@(context.Subscription.Id)"
token-quota="2000000"
token-quota-period="monthly"
tokens-per-minute="999999999"
estimate-prompt-tokens="true" />
</inbound>
</policies>
Kvoteberegning for offentlig sektor
Eksempel for en etat med 50 ansatte som bruker AI-tjenester:
| Brukerkategori | Antall | TPM per bruker | Månedlig kvote per bruker | Total månedlig |
|---|---|---|---|---|
| Power users | 5 | 10 000 | 500 000 | 2 500 000 |
| Standard users | 30 | 3 000 | 100 000 | 3 000 000 |
| Light users | 15 | 1 000 | 30 000 | 450 000 |
| Totalt | 50 | - | - | 5 950 000 |
Buffer-anbefaling: Legg til 20-30% buffer for uforutsette topper.
Multi-region-hensyn
Rate limits er regionale
APIM Gateway (Norway East) → Rate limit counter: 50 000 TPM
APIM Gateway (Sweden Central) → Rate limit counter: 50 000 TPM
(separate tellere!)
Viktig: I multi-region deployments har hver regional gateway sin egen rate limit-teller. En konsument kan potensielt bruke 50 000 TPM i Norway East OG 50 000 TPM i Sweden Central = 100 000 TPM totalt.
Kvoter er globale
APIM Instance (global)
├── Gateway (Norway East) ─┐
└── Gateway (Sweden Central) ─┤── Delt kvote-teller: 2 000 000/mnd
└── (synkronisert globalt)
Anbefaling for offentlig sektor: Bruk kvoter for total kostnadskontroll, og rate limits for burst-beskyttelse. Vurder å justere regionale rate limits basert på forventet trafikkfordeling.
Feilhåndtering og respons-headers
HTTP-responser ved overskridelse
| Scenario | HTTP-kode | Response header | Body |
|---|---|---|---|
| TPM rate limit nådd | 429 | Retry-After: <sekunder> |
Feilmelding med gjenstående tokens |
| Kvote brukt opp | 403 | Retry-After: <sekunder til reset> |
Feilmelding med kvoteinformasjon |
| Prompt estimat overskrider | 429 | Retry-After: <sekunder> |
Avvist uten backend-kall |
Bruk av context-variabler
<policies>
<inbound>
<llm-token-limit
counter-key="@(context.Subscription.Id)"
tokens-per-minute="50000"
remaining-tokens-variable-name="remainingTokens"
tokens-consumed-variable-name="tokensConsumed"
retry-after-variable-name="retryAfter" />
</inbound>
<outbound>
<!-- Inkluder gjenstående tokens i respons-header -->
<set-header name="X-Remaining-Tokens" exists-action="override">
<value>@(context.Variables.GetValueOrDefault<int>("remainingTokens").ToString())</value>
</set-header>
<set-header name="X-Tokens-Consumed" exists-action="override">
<value>@(context.Variables.GetValueOrDefault<int>("tokensConsumed").ToString())</value>
</set-header>
</outbound>
</policies>
Burst Allowances og Concurrency Control
Kombinere token limit med concurrency limit
For å beskytte mot mange samtidige store requests:
<policies>
<inbound>
<!-- Maks 10 samtidige requests per subscription -->
<limit-concurrency key="@(context.Subscription.Id)" max-count="10">
<!-- Token rate limiting innenfor concurrency-grensen -->
<llm-token-limit
counter-key="@(context.Subscription.Id)"
tokens-per-minute="50000"
estimate-prompt-tokens="true" />
</limit-concurrency>
</inbound>
</policies>
Burst-håndtering med Token Bucket (V2 tiers)
Token bucket-algoritmen i V2 tiers tillater naturlig burst-kapasitet:
| Konfigurasjon | Effektiv burst | Sustained rate |
|---|---|---|
| TPM=50 000 | Opp til 50 000 tokens i enkelt-request | ~833 tokens/sek |
| TPM=100 000 | Opp til 100 000 tokens i enkelt-request | ~1 667 tokens/sek |
| TPM=200 000 | Opp til 200 000 tokens i enkelt-request | ~3 333 tokens/sek |
Monitorering av token-forbruk
Token-metrikk policy
<outbound>
<llm-emit-token-metric namespace="ai-token-usage">
<dimension name="Subscription" value="@(context.Subscription.Id)" />
<dimension name="Etat" value="@(context.Request.Headers.GetValueOrDefault("x-etat", "ukjent"))" />
<dimension name="Model" value="@(context.Request.Headers.GetValueOrDefault("x-model", "default"))" />
</llm-emit-token-metric>
</outbound>
KQL-spørring for token-forbruk
customMetrics
| where name == "Total Tokens"
| extend etat = tostring(customDimensions["Etat"])
| summarize TotalTokens = sum(value) by etat, bin(timestamp, 1h)
| order by timestamp desc
| render timechart
Azure Monitor Alert for kvote-overskridelse
{
"type": "Microsoft.Insights/metricAlerts",
"properties": {
"criteria": {
"metricName": "Total Tokens",
"metricNamespace": "ai-token-usage",
"operator": "GreaterThan",
"threshold": 4000000,
"timeAggregation": "Total",
"dimensions": [
{
"name": "Subscription",
"operator": "Include",
"values": ["*"]
}
]
},
"windowSize": "P1D",
"evaluationFrequency": "PT1H"
}
}
Tier-kompatibilitet
| Policy | Classic | V2 | Consumption | Self-hosted | Workspace |
|---|---|---|---|---|---|
azure-openai-token-limit |
Ja | Ja | Nei | Ja | Ja |
llm-token-limit |
Ja | Ja | Nei | Ja | Ja |
azure-openai-emit-token-metric |
Ja | Ja | Nei | Ja | Ja |
llm-emit-token-metric |
Ja | Ja | Nei | Ja | Ja |
rate-limit-by-key |
Ja | Ja | Nei | Ja | Ja |
quota-by-key |
Ja | Nei | Nei | Ja | Ja |
Merk: Token-policies er IKKE tilgjengelige i Consumption tier. For AI-workloads, bruk minimum Basic v2 eller Standard v2.
Best Practices
Anbefalt oppsett for norsk offentlig sektor
- Bruk
llm-token-limitfremforazure-openai-token-limitfor fremtidig fleksibilitet - Aktiver
estimate-prompt-tokensfor å avvise for store requests tidlig - Kombiner TPM rate limit med månedlig kvote for dobbel beskyttelse
- Bruk subscription-basert counter-key som primær granularitet
- Legg til custom header-dimensjoner for kostnadsrapportering per etat/prosjekt
- Sett opp Azure Monitor Alerts ved 80% kvotebruk
- Dokumenter kvoteallokeringer i tjenestekataloger og SLA-er
- Test med GenAI Gateway Toolkit for å verifisere policy-oppførsel under last
For Cosmo
- Token rate limiting er den viktigste AI gateway-policyen -- alltid start her når du setter opp APIM for Azure OpenAI. Bruk
llm-token-limitsom standard, medestimate-prompt-tokens="true"for tidlig avvisning. - Counter-key-strategien bestemmer granulariteten: subscription-basert for team-nivå, custom headers for etat/prosjekt, JWT claims for bruker-nivå. For offentlig sektor anbefales subscription per team + custom header for kostnadsrapportering.
- V2 tiers bruker token bucket-algoritme som håndterer bursts bedre enn sliding window i Classic tiers -- anbefal Standard v2 for nye deployments.
- Rate limits er regionale (per gateway-instans), men kvoter er globale. I multi-region oppsett må du dimensjonere rate limits per region, men bruke kvoter for total kostnadskontroll.
- Kombiner alltid
llm-token-limitmedllm-emit-token-metricfor full observabilitet, og sett opp alerts ved 80% kvotebruk for proaktiv kapasitetsstyring.