# API Rate Limiting and Resilience Patterns

**Last updated:** 2026-04 | Verified: MCP 2026-04
**Status:** GA
**Category:** Copilot Extensibility & Integration

---

## Introduksjon

Rate limiting og resilience patterns er kritiske for å bygge robuste Microsoft AI-applikasjoner som håndterer transiente feil, throttling og kapasitetsbegrensninger på en elegant måte. Microsofts AI-plattformer (Azure OpenAI, Copilot Studio, M365 Copilot) implementerer throttling for å beskytte infrastruktur og sikre rettferdig ressursfordeling. Effektiv håndtering av disse begrensningene skiller en prototyp fra en produksjonsklar løsning.

Denne referansen dekker:
- **Retry patterns** med exponential backoff for transiente feil
- **Rate limiting patterns** for å unngå throttling
- **Circuit breaker patterns** for varige feil
- **Plattformspesifikke kvotegrenser** (Azure OpenAI, Copilot Studio)
- **Implementeringsmønstre** med kodeeksempler

**Confidence:** Verified (Microsoft Learn MCP, januar 2026) | Re-verified: MCP 2026-04

---

## Kjernekomponenter / Nøkkelegenskaper

### 1. Retry Pattern (Retry etter transiente feil)

**Formål:** Håndtere kortvarige feil (nettverkstap, midlertidig utilgjengelighet, timeouts) ved automatisk å prøve operasjonen på nytt etter en passende forsinkelse.

**Nøkkelstrategier:**
- **Cancel:** Avbryt hvis feilen ikke er transient eller sannsynligvis vil gjenta seg
- **Retry immediately:** For sjeldne feil (f.eks. korrupt nettverkspakke)
- **Retry after delay:** For vanlige connectivity/busy-feil — vent før retry (anbefalt)

**Exponential backoff:** Vent 2s → 4s → 8s → 16s mellom forsøk for å unngå å overbelaste en allerede busy service.

**Viktighetsgrad:**
- Innebygd retry i mange Microsoft-biblioteker (Entity Framework, Azure SDK)
- Logg tidlige feil som informasjon, kun siste forsøk som error
- Idempotens-krav: operasjonen må være trygg å kjøre flere ganger

**Verified:** [Retry pattern - Azure Architecture Center](https://learn.microsoft.com/en-us/azure/architecture/patterns/retry)

### 2. Rate Limiting Pattern (Kontrollert trafikk)

**Formål:** Redusere throttling-feil ved å kontrollere antall requests sendt til en service over tid, innenfor servicens kapasitetsgrenser.

**Problem som løses:**
En naiv "retry on error"-tilnærming kan sende 3x mer trafikk enn nødvendig (eksempel: 10 000 records, 2 000 RU/s kapasitet = 30 000 forsøk i stedet for 10 000).

**Løsning:**
1. **Bruk durable messaging** (Azure Service Bus, Event Hubs, Queue Storage) som buffer
2. **Dequeue i kontrollert tempo** (f.eks. 20 requests hvert 200ms i stedet for 100/sekund) — sender et jevnere dataflyt og forhindrer bottlenecks ved bursts
3. **Distributed lease management** for multiple prosesser (Azure Blob lease eller Zookeeper/Redis/etcd/Consul)
4. **Logisk partisjonering:** Deler kapasiteten i partisjoner (f.eks. 20 partisjoner à 25 req/s for 500 req/s totalt) — prosesser konkurrerer om eksklusive blob-leases per partisjon

**Fordeler:**
- Redusert trafikk og færre feil
- Forutsigbar throughput
- Lavere minneforbruk (dequeue kun når kapasitet er tilgjengelig)

**Verified:** [Rate Limiting pattern - Azure Architecture Center](https://learn.microsoft.com/en-us/azure/architecture/patterns/rate-limiting-pattern)

**Eksempel (Cosmos DB med 20 000 RU/s kapasitet, 10 000 records à 10 RU):**
- Naiv retry: 30 000 requests sendt (10K + 8K + 6K + 4K + 2K) med 20 000 feil
- Med rate limiting: 10 000 requests, ingen throttling-feil, forutsigbar gjennomstrømningstid

### 3. Circuit Breaker Pattern (Beskyttelse mot varige feil)

**Formål:** Forhindre at applikasjonen spammer en service som er nede eller ikke responderer, ved å "åpne kretsen" etter N feilede forsøk.

**Tilstander:**
- **Closed:** Normal drift, requests går gjennom
- **Open:** Etter X feil — blokkerer alle requests
- **Half-Open:** Periodisk tillat én prøve-request for å sjekke om service er tilbake

**Forskjell fra Retry:**
- Retry forventer at feilen løser seg raskt
- Circuit Breaker forventer langvarig feil og beskytter mot waste

**Kombinasjon:** Bruk Retry pattern med Circuit Breaker for optimal resilience.

**Verified:** [Circuit Breaker pattern - Azure Architecture Center](https://learn.microsoft.com/en-us/dotnet/architecture/cloud-native/application-resiliency-patterns#circuit-breaker-pattern)

### 4. HTTP Response Headers for Rate Limiting

**Standard headers** (RateLimit-* eller X-RateLimit-*):
- `RateLimit-Remaining`: Antall requests igjen i nåværende window
- `RateLimit-Reset`: Tidspunkt når grensen resettes
- `Retry-After`: Antall sekunder å vente før neste request (ved 429 Too Many Requests)

**Status codes:**
- **429 Too Many Requests:** Rate limit overskredet
- **503 Service Unavailable:** Midlertidig overbelastet (retry etter `Retry-After`)

**Best practice:**
- Sjekk `RateLimit-Remaining` og throttle *før* du når 0
- Respekter `Retry-After` header ved 429-feil

**Verified:** [What is rate limiting? - Microsoft Cloud Dev](https://learn.microsoft.com/en-us/microsoft-cloud/dev/dev-proxy/concepts/what-is-rate-limiting)

---

## Arkitekturmønstre

### Mønster 1: Retry med Exponential Backoff (C#)

```csharp
using Microsoft.Azure.WebJobs;

[FunctionName("EventHubTrigger")]
[ExponentialBackoffRetry(5, "00:00:04", "00:15:00")]
public static async Task Run([EventHubTrigger("myHub", Connection = "EventHubConnection")] EventData[] events, ILogger log)
{
    // Function logic her
    // Retries automatisk 5 ganger med 4s min, 15 min max delay
}
```

**Forklaring:**
- 5 retry-forsøk
- Initial delay: 4 sekunder
- Max delay: 15 minutter
- Eksponentiell økning mellom forsøk

**Use case:** Azure Functions, Event Hubs triggers, Cosmos DB triggers.

**Verified:** [Retry policies - Azure Functions](https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-error-pages)

### Mønster 2: Custom Retry Logic med Transient Fault Handling (Teams Bot)

```csharp
// Definer retry-strategi
var exponentialBackoffRetryStrategy = new ExponentialBackoffRetryStrategy(
    3,                              // 3 forsøk
    TimeSpan.FromSeconds(2),        // Min backoff
    TimeSpan.FromSeconds(20),       // Max backoff
    TimeSpan.FromSeconds(1)         // Jitter delta (+/- 20%)
);

// Definer retry policy
var retryPolicy = new RetryPolicy(new BotSdkTransientExceptionDetectionStrategy(), exponentialBackoffRetryStrategy);

// Utfør bot-operasjon med retry
await retryPolicy.ExecuteAsync(() => connector.Conversations.ReplyToActivityAsync((Activity)reply)).ConfigureAwait(false);
```

**Transient Exception Detection (429 rate limit):**
```csharp
public class BotSdkTransientExceptionDetectionStrategy : ITransientErrorDetectionStrategy
{
    List<int> transientErrorStatusCodes = new List<int>() { 429 };

    public bool IsTransient(Exception ex)
    {
        if (ex.Message.Contains("429"))
            return true;

        HttpResponseMessageWrapper? response = null;
        if (ex is HttpOperationException httpOperationException)
            response = httpOperationException.Response;

        return response != null && transientErrorStatusCodes.Contains((int)response.StatusCode);
    }
}
```

**Forklaring:**
- Sjekker om feil er HTTP 429 (rate limit)
- Retry kun for transiente feil
- Jitter (+/- 20%) sprer load fra multiple klienter

**Use case:** Teams bots, Power Virtual Agents, Copilot Studio bots.

**Verified:** [Optimize bot with rate limiting in Teams](https://learn.microsoft.com/en-us/microsoftteams/platform/bots/how-to/rate-limit)

### Mønster 3: Rate Limiting med Queue + Lease-basert Kapasitetsstyring

```text
[API] → [Queue A / Queue B] → [Job Processor] → [Rate-limited Service]
                                      ↓
                                [Blob Lease Partitions]
```

**Workflow:**
1. API enqueuer records til durable queue (Azure Service Bus/Event Hubs)
2. Job Processor forsøker å lease blob-partitions (Azure Blob Storage)
3. For hver leaset partition → X requests/sekund kapasitet
4. Processor dequeuer kun det som kan prosesseres innenfor kapasitet
5. Lease expires → processor må re-lease eller redusere throughput

**Eksempel:**
- Service tillater 500 req/s
- Oppretter 20 partitions × 25 req/s
- Process A leaser 4 partitions → 100 req/s
- Process B leaser 2 partitions → 50 req/s

**Fordeler:**
- Multiple unkoordinerte prosesser kan dele kapasitet
- Redusert minnebruk (dequeue kun ved kapasitet)
- Færre throttling-feil

**Verified:** [Rate Limiting pattern - Azure Architecture Center](https://learn.microsoft.com/en-us/azure/architecture/patterns/rate-limiting-pattern)

### Mønster 4: Batch Job Queueing med Exponential Backoff (Azure OpenAI)

```python
import time
from openai import BadRequestError

max_retries = 10
retries = 0
initial_delay = 5
delay = initial_delay

while True:
    try:
        batch_response = client.batches.create(
            input_file_id=file_id,
            endpoint="/chat/completions",
            completion_window="24h",
        )
        batch_id = batch_response.id
        print(f"✅ Batch created successfully after {retries} retries")
        break

    except BadRequestError as e:
        if 'token_limit_exceeded' in str(e):
            retries += 1
            if retries >= max_retries:
                raise

            print(f"⏳ Token limit exceeded. Waiting {delay}s (retry {retries}/{max_retries})")
            time.sleep(delay)
            delay *= 2  # Exponential backoff
        else:
            raise
```

**Forklaring:**
- Håndterer token_limit_exceeded for Azure OpenAI batch jobs
- Fail-fast hvis token quota nådd (nytt i 2025)
- Exponential backoff: 5s → 10s → 20s → 40s...

**Use case:** Store batch-operasjoner (Azure OpenAI, Azure AI Foundry).

**Verified:** [Batch deployments - Azure OpenAI](https://learn.microsoft.com/en-us/azure/ai-foundry/openai/how-to/batch)

---

## Beslutningsveiledning

### Når bruke hvilken pattern?

| Pattern | Use Case | Eksempel |
|---------|----------|----------|
| **Retry (immediate)** | Sjeldne, transiente feil | Korrupt nettverkspakke |
| **Retry (exponential backoff)** | Vanlige transiente feil (connectivity, busy) | Azure OpenAI 429, Cosmos DB throttling |
| **Rate Limiting** | Forutsigbar throttling-grense | Azure OpenAI TPM/RPM quotas, Copilot Studio generative AI limits |
| **Circuit Breaker** | Langvarige feil (service nede) | Avhengighet på ekstern API som er nede i minutter |
| **Kombiner Retry + Circuit Breaker** | Kritiske applikasjoner | E-handel checkout, helsesektorsystemer |

### Sjekkliste før implementering

**1. Er operasjonen idempotent?**
- Ja → Trygt å retry
- Nei → Implementer idempotency token eller accept duplicate risk

**2. Hva er tjenestens throttling-grense?**
- Sjekk dokumentasjon for TPM (tokens per minute), RPM (requests per minute)
- Eksempler: Azure OpenAI Standard tier = 150K TPM (gpt-4o), Copilot Studio = per hour/minute quotas

**3. Har applikasjonen multiple workstreams?**
- Ja → Bruk shared rate limiter eller separate capacity pools
- Nei → Simpel retry policy holder

**4. Er feilen transient eller varig?**
- Transient (429, 503) → Retry
- Varig (500 Internal Server Error gjentatte ganger) → Circuit Breaker

---

## Integrasjon med Microsoft-stakken

### Azure OpenAI Service

**Quota limits (per deployment):**
- **gpt-4o** (Global Standard, Default tier): 450K TPM, 2.7K RPM
- **gpt-4o-mini** (Default tier): 2M TPM, 12K RPM
- **o1-preview** (Default tier): 300K TPM, 50 RPM

**429 Error Scenarios:**
1. **Rate Limit Exceeded:** TPM/RPM quota overskredet → retry etter `Retry-After`
2. **High System Demand:** System under load → retry etter suggested time

**Best practice:**
- Sett `max_tokens` til minimum nødvendig (reduserer TPM-forbruk)
- Bruk quota management for å øke TPM på high-traffic deployments
- Implementer retry logic med exponential backoff
- Unngå skarpe workload-endringer (gradvis økning)

**Verified:** [Quotas and limits - Azure OpenAI](https://learn.microsoft.com/en-us/azure/ai-foundry/openai/quotas-limits), [Manage quota - Azure OpenAI](https://learn.microsoft.com/en-us/azure/ai-foundry/openai/how-to/quota)

### Copilot Studio

**Throttling error codes:**
- **GenAISearchandSummarizeRateLimitReached:** Søk/summarize quota nådd (per hour/minute per Dataverse environment)
- **GenAIToolPlannerRateLimitReached:** Generative orchestration quota nådd
- **OpenAIRateLimitReached:** Max generative answers reached

**Løsninger:**
1. **Licensing:** Kjøp flere capacity packs eller bytt til pay-as-you-go
2. **Request rate limit increase:** Kontakt Microsoft Support (kun for pay-as-you-go environments)
3. **Optimize bot:** Bruk express mode, cache retrieved info, bruk direct connector calls i stedet for Power Automate flows

**Flow timeout:** Max 100 sekunder før timeout → optimaliser flow logic, flytt non-critical logic etter 'Return value(s)' step.

**Verified:** [Resolve throttling errors in agents](https://learn.microsoft.com/en-us/troubleshoot/power-platform/copilot-studio/licensing/throttling-errors-agents), [Error codes - Copilot Studio](https://learn.microsoft.com/en-us/troubleshoot/power-platform/copilot-studio/authoring/error-codes)

### Power Automate (Cloud Flows)

**Throttling limits:**
- API request limits per 24 timer (avhenger av lisens)
- Service protection API limits (Dataverse): 429 med `Retry-After` header

**Best practice:**
- Følg `Retry-After` interval (lengre delay hvis du sender demanding requests)
- Start med lavt request-volum, øk gradvis til du treffer limit
- Cache data i variabler i stedet for multiple API calls
- Bruk direct connector calls (raskere enn flows fra Copilot Studio)

**Verified:** [Retry operations - Dynamics 365](https://learn.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/data-entities/service-protection-retry-operations)

### Microsoft Teams Bots

**Rate limits:**
- Per bot per thread limit
- Per bot global limit

**Best practice:**
- Detect transient exceptions (429 status code)
- Implement exponential backoff med jitter
- Unngå overdreven polling

**Verified:** [Rate limiting in Teams](https://learn.microsoft.com/en-us/microsoftteams/platform/bots/how-to/rate-limit)

---

## Offentlig sektor (Norge)

### Compliance og logging

**GDPR/Personvern:**
- Logg kun feilinformasjon (status codes, timestamps), ikke persondata
- Tidlige retry-feil = INFO, kun siste forsøk = ERROR (unngå flooding av PII i logs)

**Sporbarhet:**
- Implementer correlation IDs for å spore requests gjennom retry-forsøk
- Aggreger feilstatistikk for å identifisere underliggende problemer (f.eks. persistent throttling = kapasitetsøkning nødvendig)

### Kostnadskontroll

**Rate limiting reduserer kostnader:**
- Færre unødvendige API-kall (Azure OpenAI, Copilot Studio)
- Lavere TPM-forbruk = mindre behov for capacity packs

**Example:**
- Naiv retry (10K records, 30K requests sent) vs. rate limiting (10K records, 10K requests sent) = 66% redusert API-forbruk

### Tilgjengelighet og SLA

**SLA-krav:**
- Standard tier (Azure OpenAI) har *ingen latency SLA* og variabel latency ved high load
- For kritiske tjenester: vurder **Provisioned Throughput** (Premium tier) for forutsigbar ytelse
- Circuit Breaker beskytter mot cascade failures i multi-tjeneste-arkitekturer

---

## Kostnad og lisensiering

### Azure OpenAI

**Quota management (gratis):**
- Juster TPM/RPM per deployment (ingen ekstra kostnad)

**Provisioned Throughput (PTU):**
- Fast monthly cost per PTU
- Bedre forutsigbarhet og lavere latency
- Egnet for prod-workloads med strenge SLA-krav

### Copilot Studio

**Capacity packs:**
- Kjøp ekstra capacity for å øke quotas (generative AI messages)

**Pay-as-you-go:**
- Betale per bruk (Copilot credits)
- Overage enforcement: "Agent unavailable" når quota nådd (tilbake online innen 5 min etter capacity økning)

### Power Automate

**API request limits:**
- Inkludert i lisens (varierer per plan: F1, P1, P2, etc.)
- Overskridelse = throttling (429 errors)

**Verified:** [Copilot Studio quotas](https://learn.microsoft.com/en-us/microsoft-copilot-studio/requirements-quotas), [Power Platform API limits](https://learn.microsoft.com/en-us/power-platform/admin/api-request-limits-allocations)

---

## For arkitekten (Cosmo)

### Når anbefale hvilken løsning?

**Prototyping/POC:**
- Start med innebygd retry (Azure SDK, Entity Framework)
- Acceptable å treffe 429-feil under testing

**Production-ready:**
- **Implementer alle 3:** Retry + Rate Limiting + Circuit Breaker
- Bruk durable messaging (Event Hubs, Service Bus) som buffer
- Monitorér `RateLimit-Remaining` headers proaktivt

**Kritiske tjenester (helse, finans, offentlig sektor):**
- Azure OpenAI Provisioned Throughput (PTU) for SLA
- Distributed rate limiting for multi-instance apps
- Correlation IDs for full observability
- Graceful degradation ved circuit breaker open (vis cached/fallback data)

### Red Flags (når å eskalere til PTU/Premium)

1. **Hyppig 429-feil til tross for retry logic** → Kapasitet for lav, vurder PTU
2. **Variabel latency påvirker brukeropplevelse** → Standard tier har ingen latency SLA
3. **Multiple apps konkurrerer om samme deployment** → Separer deployments eller bruk distributed lease
4. **Batch jobs tar timer lenger enn forventet** → Rate limiting med queue kan halvere tid

### Implementeringsrekkefølge (anbefalt)

**Fase 1: Basic Resilience**
1. Implementer retry med exponential backoff (Azure SDK default eller custom policy)
2. Logg 429-feil og analyser frekvens

**Fase 2: Proactive Rate Limiting**
3. Bruk `RateLimit-Remaining` header for å throttle *før* 429
4. Implementer queue-basert rate limiting hvis batch-operasjoner

**Fase 3: Advanced Resilience**
5. Legg til Circuit Breaker for kritiske avhengigheter
6. Implementer distributed lease for multi-instance apps
7. Monitorér og tune retry/backoff-parametere basert på prod-data

### Spørsmål å stille kunden

1. **Hva er forventet request-volum?** (beregn TPM/RPM-behov)
2. **Hva er SLA-krav for latency?** (Standard vs. PTU)
3. **Har dere multiple applikasjoner som deler samme Azure OpenAI deployment?** (distributed rate limiting)
4. **Er operasjonene batch-orienterte eller real-time?** (queue vs. direct retry)
5. **Hva er akseptabel feilrate?** (0.1% = streng, 1% = moderat)

### Testing og Validering

**Load testing:**
- Simuler 2x forventet load for å verifisere retry logic
- Sjekk at app håndterer 429-feil uten crash
- Verifiser at circuit breaker åpner/lukker korrekt

**Chaos engineering:**
- Simuler service downtime (503 errors) for å teste circuit breaker
- Sjekk at app degrader gracefully (fallback, cached data)

**Metrics å monitorere:**
- 429 error rate (mål: < 1% av requests)
- Retry success rate (mål: > 95%)
- P95/P99 latency (inkludert retry delays)
- Circuit breaker state transitions (Open/Closed/Half-Open)

---

## Kilder og verifisering

**Alle kilder verifisert via Microsoft Learn MCP (januar 2026):**

1. [Retry pattern - Azure Architecture Center](https://learn.microsoft.com/en-us/azure/architecture/patterns/retry)
2. [Rate Limiting pattern - Azure Architecture Center](https://learn.microsoft.com/en-us/azure/architecture/patterns/rate-limiting-pattern)
3. [Circuit Breaker pattern - Cloud-Native .NET](https://learn.microsoft.com/en-us/dotnet/architecture/cloud-native/application-resiliency-patterns)
4. [What is rate limiting? - Microsoft Cloud Dev](https://learn.microsoft.com/en-us/microsoft-cloud/dev/dev-proxy/concepts/what-is-rate-limiting)
5. [How to handle API throttling - Microsoft Cloud Dev](https://learn.microsoft.com/en-us/microsoft-cloud/dev/dev-proxy/concepts/how-to-handle-api-throttling)
6. [Azure OpenAI quotas and limits](https://learn.microsoft.com/en-us/azure/ai-foundry/openai/quotas-limits)
7. [Manage Azure OpenAI quota](https://learn.microsoft.com/en-us/azure/ai-foundry/openai/how-to/quota)
8. [Batch deployments - Azure OpenAI](https://learn.microsoft.com/en-us/azure/ai-foundry/openai/how-to/batch)
9. [Resolve throttling errors in Copilot Studio agents](https://learn.microsoft.com/en-us/troubleshoot/power-platform/copilot-studio/licensing/throttling-errors-agents)
10. [Error codes - Copilot Studio](https://learn.microsoft.com/en-us/troubleshoot/power-platform/copilot-studio/authoring/error-codes)
11. [Optimize bot with rate limiting in Teams](https://learn.microsoft.com/en-us/microsoftteams/platform/bots/how-to/rate-limit)
12. [Retry operations - Dynamics 365](https://learn.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/data-entities/service-protection-retry-operations)
13. [Retry policies - Azure Functions](https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-error-pages)

**MCP Calls:** 6 (3 searches, 2 fetches, 1 code sample search)
**Unique URLs:** 13 sources
