# Request Batching and Response Aggregation

**Last updated:** 2026-02
**Status:** GA
**Category:** Cost Optimization & FinOps for AI

---

## Introduksjon

Request batching og response aggregation er kritiske kostnadsoptimaliseringsteknikker for AI-løsninger som gjør det mulig å konsolidere flere API-forespørsler i én enkelt nettverksoperasjon. I stedet for å sende hundrevis eller tusenvis av individuelle API-kall, kan applikasjoner samle disse i batches, redusere nettverkslatens, minimere API throttling-risiko og drastisk kutte kostnader.

For Microsoft AI-stakken er batching spesielt relevant i to hovedscenarier: **asynchronous batch processing** (Azure OpenAI Batch API, Azure Machine Learning batch endpoints) og **synchronous request aggregation** (Microsoft Graph JSON batching). Azure OpenAI Batch API tilbyr 50% kostnadsreduksjon sammenlignet med standard global deployments, med separert token quota og 24-timers SLA. Microsoft Graph JSON batching tillater opptil 20 individuelle forespørsler i ett enkelt HTTP-kall, noe som reduserer network roundtrips og forbedrer effektivitet.

Denne teknikken er ikke bare en optimaliseringsøvelse — den er ofte nødvendig for å operere innenfor rate limits og quota, spesielt i offentlig sektor der budsjetter er stramme og skalerbarhetsbehov er økende. Riktig implementering krever forståelse av payload structure, response unpacking, error handling for partial failures, og trade-offs mellom latency og throughput.

---

## Kjernekomponenter

### Azure OpenAI Batch API

| Komponent | Beskrivelse |
|-----------|-------------|
| **Input file (JSONL)** | JSON Lines-format med én request per linje, inkludert `custom_id` for korrelasjon |
| **Global-Batch deployment** | Dedikert deployment-type med 50% lavere pris enn global standard |
| **Enqueued token quota** | Separat quota som ikke forstyrrer online workloads |
| **24-hour completion window** | Target SLA for batch processing (jobs kan ta lenger, men utløper ikke) |
| **Output file** | JSONL-resultatfil med responses korrelert via `custom_id` |
| **Exponential backoff queuing** | Støtte i utvalgte regioner for automatisk retry når token quota er tilgjengelig |

### Microsoft Graph JSON Batching

| Komponent | Beskrivelse |
|-----------|-------------|
| **$batch endpoint** | OData-standard URL path segment (`/v1.0/$batch` eller `/beta/$batch`) |
| **requests array** | Samling av individuelle requests med `id`, `method`, `url`, `headers`, `body` |
| **responses array** | Samling av individuelle responses med `id`, `status`, `headers`, `body` |
| **dependsOn property** | Støtter sekvensielle dependencies mellom requests (optional) |
| **Batch size limit** | Maksimalt 20 requests per batch |
| **Correlation via id** | Responses returneres ikke i samme rekkefølge som requests |

### Azure Machine Learning Batch Endpoints

| Komponent | Beskrivelse |
|-----------|-------------|
| **Batch endpoint** | Asynkron inferencing-tjeneste med auto-scaling compute clusters |
| **Pipeline component deployments** | Reusable MLOps components for komplekse inference workflows |
| **Low-priority VMs** | Kostnadsreduksjon med spot capacity (auto-recovery ved deallocations) |
| **Scale-to-zero clusters** | Ingen kostnad når idle, auto-provision ved job start |
| **Parallelization** | Distribuert processing av store datasett spredt over flere filer |

---

## Arkitekturmønstre

### 1. Client-Side Batching (Synchronous)

**Egnet for:** Microsoft Graph, REST APIs med $batch-støtte, real-time aggregation

**Mønster:**
- Klienten samler flere requests i én batch-payload
- Sender POST til `$batch`-endpoint
- Mottar aggregert response med individuelle resultater
- Parser og distribuerer resultater tilbake til opprinnelige requesters

**Eksempel (Microsoft Graph):**

```json
POST https://graph.microsoft.com/v1.0/$batch
{
  "requests": [
    {"id": "1", "method": "GET", "url": "/me/drive/root"},
    {"id": "2", "method": "GET", "url": "/me/planner/tasks"},
    {"id": "3", "method": "GET", "url": "/groups/{id}/calendar"}
  ]
}
```

**Response:**
```json
{
  "responses": [
    {"id": "1", "status": 200, "body": {...}},
    {"id": "2", "status": 200, "body": {...}},
    {"id": "3", "status": 403, "body": {"error": {...}}}
  ]
}
```

**Fordeler:**
- Reduserer network roundtrips (1 HTTP call vs. N calls)
- Lavere latency for små-til-medium batches (< 20 items)
- Synkron response — lettere feilhåndtering

**Ulemper:**
- Begrenset til 20 requests (Microsoft Graph)
- Ingen kostnadsreduksjon per request (kun nettverkseffektivitet)
- Alle requests må vente på tregeste request før response returneres

---

### 2. Server-Side Asynchronous Batching

**Egnet for:** Azure OpenAI, store datasett, ikke-tidsensitive workloads, kostnadsoptimalisering

**Mønster:**
- Klienten laster opp batch input file (JSONL) til Azure Storage eller OpenAI Files API
- Sender batch job request med file ID og completion window
- Server prosesserer asynkront med separat quota
- Klienten poller job status til completion
- Henter output file og parser resultater

**Eksempel (Azure OpenAI Batch API):**

```python
# Upload input file
with open("batch_input.jsonl", "rb") as f:
    file = client.files.create(file=f, purpose="batch")

# Create batch job
batch = client.batches.create(
    input_file_id=file.id,
    endpoint="/chat/completions",
    completion_window="24h"
)

# Poll for completion
while batch.status not in ["completed", "failed", "cancelled"]:
    time.sleep(60)
    batch = client.batches.retrieve(batch.id)

# Download results
output_file_id = batch.output_file_id
content = client.files.content(output_file_id)
```

**Fordeler:**
- 50% kostnadsreduksjon (Azure OpenAI Batch API)
- Separat quota — ingen impact på online workloads
- Skalerer til millioner av requests (ingen 20-request limit)
- Auto-parallelization på server-side

**Ulemper:**
- Høyere latency (24-hour SLA, ofte raskere men ingen garantier)
- Asynkron — krever polling eller webhook-notifikasjoner
- Mer kompleks feilhåndtering (partial failures i output file)

---

### 3. Queue-Based Batching with Aggregation

**Egnet for:** Event-driven arkitekturer, ujevn last, backpressure management

**Mønster:**
- Applikasjonen sender meldinger til Azure Service Bus eller Storage Queue
- Azure Function eller Logic App aggregerer meldinger i batches (time window eller count threshold)
- Sender konsolidert batch til AI-tjeneste (Azure OpenAI, Cognitive Services)
- Distribuerer resultater tilbake via queue eller Event Grid

**Eksempel (Azure Functions + Service Bus):**

```python
@app.service_bus_queue_trigger(
    arg_name="msgs",
    queue_name="ai-requests",
    connection="ServiceBusConnection",
    cardinality="many"
)
def batch_processor(msgs: List[func.ServiceBusMessage]):
    batch_input = [json.loads(msg.get_body().decode()) for msg in msgs]

    # Send to Azure OpenAI Batch API or process directly
    responses = process_batch(batch_input)

    # Write results to output queue/storage
    for msg, response in zip(msgs, responses):
        write_result(msg.correlation_id, response)
```

**Fordeler:**
- Decoupling av producers og consumers
- Auto-scaling basert på queue depth
- Resilience ved failures (retry logic, dead-letter queues)
- Kan kombineres med både sync og async batching

**Ulemper:**
- Økt kompleksitet (flere komponenter)
- Potensiell latency overhead (buffering time)
- Ekstra kostnader for queue/messaging services

---

## Beslutningsveiledning

### Når Bruke Hvilken Batching-Strategi?

| Kriterium | Client-Side Sync | Server-Side Async | Queue-Based |
|-----------|------------------|-------------------|-------------|
| **Request volume** | < 20 per batch | > 100 per batch | Varierende/ujevn |
| **Latency-krav** | < 5 sekunder | > 1 minutt OK | Moderat (10-60 sek) |
| **Kostnadsoptimalisering** | Lav (kun nettverk) | Høy (50% rabatt) | Moderat (queue costs) |
| **Error handling** | Synkron, enkel | Asynkron, kompleks | Resilient (retry/DLQ) |
| **Skalerbarhet** | Lav-moderat | Meget høy | Høy |
| **Brukstilfeller** | Multi-resource GET, form submissions | Bulk document summarization, content generation | Event-driven AI, webhook processing |

### Vanlige Feil (Anti-Patterns)

| Feil | Konsekvens | Anbefaling |
|------|------------|------------|
| **Batching for få items** | Overhead større enn fordel | Batch kun når N > 5-10 requests |
| **Ignorere partial failures** | Tapte data, inkonsistent state | Alltid parse individual response status codes |
| **Blokkerende polling** | Resource waste, poor UX | Bruk webhooks, Event Grid eller async/await patterns |
| **Hardkoding batch size** | Sub-optimal performance | Dynamisk sizing basert på payload size og latency targets |
| **Ikke bruke `custom_id`** | Kan ikke korrelere responses | Alltid inkluder unik ID per request |
| **Mixing sync og async i samme flow** | Race conditions, kompleksitet | Velg én strategi per use case |

### Røde Flagg

- **Rate limiting errors (429) ved ikke-batched calls** → Bytt til batching umiddelbart
- **> 50% av budget brukt på API costs** → Evaluer Azure OpenAI Batch API
- **Lange nettverk latencies (> 500ms roundtrip)** → Client-side batching kan hjelpe
- **Timeout errors på store datasett** → Server-side async batching påkrevd
- **Ujevn last med spikes** → Queue-based batching med buffering

---

## Integrasjon med Microsoft-Stakken

### Azure OpenAI Batch API

**Setup:**
1. Opprett Global-Batch deployment i Azure OpenAI resource
2. Prepare JSONL input file med standard chat completion format + `custom_id`
3. Upload file via Files API eller Azure Blob Storage
4. Create batch job med `client.batches.create()`
5. Poll job status eller subscribe til Event Grid events
6. Download output file og parse responses

**Regioner med Exponential Backoff Support:**
- australiaeast, eastus, eastus2, germanywestcentral, italynorth, northcentralus, polandcentral, swedencentral, switzerlandnorth, westus

**Pris:** 50% rabatt vs. global standard (verifiser på Azure pricing page)

### Microsoft Graph JSON Batching

**Setup:**
1. Konstruer JSON-payload med `requests` array
2. POST til `https://graph.microsoft.com/v1.0/$batch`
3. Parse `responses` array og korreler via `id` property
4. Håndter individuelle status codes (200, 403, 429, etc.)

**Limits:**
- Max 20 requests per batch
- Max URL length per request (~2000 characters)
- Throttling gjelder fortsatt per individual request

**Dependency Sequencing:**
```json
{
  "requests": [
    {"id": "1", "method": "POST", "url": "/groups", "body": {...}},
    {"id": "2", "dependsOn": ["1"], "method": "POST", "url": "/groups/$1/members/$ref", "body": {...}}
  ]
}
```

### Azure Machine Learning Batch Endpoints

**Setup:**
1. Opprett batch endpoint med Azure ML CLI/SDK
2. Deploy model eller pipeline component
3. Configure compute cluster (standard eller low-priority VMs)
4. Invoke endpoint med data asset eller storage URL
5. Monitor job progress via Azure ML studio eller SDK
6. Retrieve results fra output storage location

**Cost Optimization:**
- Bruk low-priority VMs for 60-80% kostnadsreduksjon
- Scale-to-zero clusters (kun betaler når jobs kjører)
- Override instance count og mini-batch size per job

### Azure Service Bus + Azure Functions

**Setup:**
1. Opprett Service Bus queue med session support (optional)
2. Deploy Azure Function med Service Bus trigger (`cardinality="many"`)
3. Configure batch size og max wait time
4. Process aggregated messages i function handler
5. Write results til output binding (Storage, Event Grid, etc.)

**Best Practices:**
- Bruk `maxMessageCount` (16-32) for optimal batching
- Set `maxWaitTime` (5-10 sek) for latency control
- Enable dead-letter queue for failed messages

### Azure API Management (APIM)

**Use Case:** Aggregere og batch requests til backend AI services

**Setup:**
1. Configure inbound policy med `set-body` for batch payload construction
2. Bruk `send-request` policy for parallel calls (sync batching simulation)
3. Aggregate responses i outbound policy
4. Cache results for repeat queries

---

## Offentlig Sektor (Norge)

### Databehandling og GDPR

| Vurdering | Implikasjon for Batching |
|-----------|--------------------------|
| **Data i transit** | Batch files inneholder ofte persondata → kryptering obligatorisk (HTTPS, Azure Storage encryption) |
| **Data at rest** | Azure OpenAI batch input/output files lagres midlertidig → slett etter processing (`output_expires_after`) |
| **Logging og audit** | Batch job IDs og correlation IDs må logges for sporbarhet (krav i offentlig sektor) |
| **Data residency** | Azure OpenAI: "Data stored at rest remains in designated Azure geography, while data may be processed for inferencing in any Azure OpenAI location" → vurder Schrems II |
| **Databehandleravtale** | Batch processing betraktes som databehandling → DPA med Microsoft påkrevd |

### Schrems II og EU Data Transfers

**Risiko:** Azure OpenAI Batch API kan prosessere data i andre regioner enn der ressursen er hostet.

**Mitigering:**
1. Bruk European regions (swedencentral, germanywestcentral, switzerlandnorth)
2. Evaluer TIA (Transfer Impact Assessment) for batch workloads
3. Vurder Azure AI Foundry med dedikert regional processing (når tilgjengelig)
4. Alternativt: Azure Machine Learning batch endpoints med regional compute

### Budsjettprosesser og Kostnadsforutsigbarhet

| Faktor | Anbefaling |
|--------|------------|
| **Cost estimation** | Azure OpenAI Batch API: 50% rabatt på token prices → oppdater budsjett-modeller |
| **Quota management** | Separert batch quota → dedikert budsjettpost for batch vs. online |
| **Month-to-month variance** | Batch workloads ofte mer forutsigbare (scheduled jobs) → lettere forecasting |
| **Pilot phase** | Start med små batches (100-1000 requests) → måle cost-per-request før full rollout |

### Tilgjengelighet og SLA

**Azure OpenAI Batch API SLA:** 24-timer target (best-effort, ikke garantert)

**Konsekvens for offentlig sektor:**
- Ikke egnet for kritiske, tidsensitive tjenester (bruk online deployments)
- OK for batch rapportering, nattlige summarizations, periodiske analyser
- Kombiner med online fallback for høy-prioritets requests

---

## Kostnad og Lisensiering

### Azure OpenAI Batch API Prismodell

| Deployment Type | Pris (relativ) | Use Case |
|-----------------|----------------|----------|
| **Global Standard** | 100% (baseline) | Online chat, real-time inference |
| **Global Batch** | 50% | Bulk processing, content generation, document analysis |
| **Provisioned Throughput** | Varierer (reservation-based) | Høy throughput, forutsigbar latency |

**Eksempel (GPT-4o, Januar 2026 priser — verifiser på Azure pricing page):**
- Global Standard: ~$5 per 1M input tokens, ~$15 per 1M output tokens
- Global Batch: ~$2.50 per 1M input tokens, ~$7.50 per 1M output tokens
- **Besparelse:** 50% for identiske workloads

**NOK Conversion (indikativt, 1 USD = 11 NOK):**
- Global Standard: ~55 kr / 1M input tokens, ~165 kr / 1M output tokens
- Global Batch: ~27.50 kr / 1M input tokens, ~82.50 kr / 1M output tokens

### Microsoft Graph JSON Batching

**Pris:** Ingen ekstra kostnad — standard Graph API pricing gjelder per individual request i batchen.

**Fordel:** Kun nettverkseffektivitet, ikke direkte kostnadsreduksjon på API calls.

### Azure Machine Learning Batch Endpoints

**Prismodell:**
- **Compute costs:** Per VM-time (AML compute clusters)
- **Storage costs:** Input/output data i Azure Storage
- **Ingen deployment costs:** Batch endpoints er gratis (betaler kun compute)

**Low-Priority VMs:**
- **Rabatt:** 60-80% vs. standard VMs
- **Risk:** Kan deallocates når Azure trenger capacity
- **Mitigering:** AML batch endpoints har auto-recovery (resumes fra siste checkpoint)

**Eksempel (Standard_D4s_v3, ca. 0.35 USD/time):**
- Standard VM: ~3.85 kr/time
- Low-Priority VM: ~0.77-1.54 kr/time

**Cost Optimization Tips:**
1. **Scale-to-zero:** Cluster auto-scales ned til 0 nodes når idle
2. **Mini-batch size tuning:** Større mini-batches → fewer VM-hours (men høyere memory usage)
3. **Instance count override:** Dynamisk øke parallelism for rush jobs, redusere for lavprioritets workloads
4. **Spot VMs:** Kombiner low-priority VMs med retry logic for max savings

---

## For Arkitekten (Cosmo)

### Spørsmål å Stille Klienten

1. **Volumetrics og Timing:**
   - "Hvor mange AI-requests forventer du daglig/månedlig?"
   - "Er det akseptabelt med 1-24 timers latency for disse requestene?"
   - "Har du spikes i last, eller er det jevnt distribuert?"

2. **Kostnadsbudsjett:**
   - "Hva er din totale AI API-budsjett per måned (NOK)?"
   - "Har dere beregnet cost-per-request for dagens løsning?"
   - "Er 50% kostnadsreduksjon viktig nok til å akseptere høyere latency?"

3. **Data og Compliance:**
   - "Inneholder batch requests personopplysninger?"
   - "Har dere TIA (Transfer Impact Assessment) for Schrems II?"
   - "Må data prosesseres i spesifikk Azure region (Norge/EU)?"

4. **Failure Handling:**
   - "Hva skjer hvis én request i en batch feiler? Retry hele batchen eller kun failed items?"
   - "Trenger dere transactional guarantees (all-or-nothing)?"
   - "Har dere monitoring og alerting for batch job failures?"

5. **Existing Infrastructure:**
   - "Bruker dere allerede Azure Service Bus, Event Grid eller Storage Queues?"
   - "Har dere CI/CD for deploying batch processing logic?"
   - "Er teamet komfortabelt med async programming patterns (polling, webhooks)?"

6. **Performance Targets:**
   - "Hva er max akseptabel latency per request?"
   - "Trenger dere real-time feedback til brukere, eller kan de vente på batch completion?"
   - "Har dere SLA-krav overfor egne sluttbrukere?"

7. **Scaling Plans:**
   - "Forventer dere 10x, 100x volum-økning neste år?"
   - "Vil dere trenge multi-region failover for batch processing?"

### Fallgruver å Unngå

| Fallgruve | Hvorfor Det Er Farlig | Mitigering |
|-----------|------------------------|------------|
| **Over-batching** | Latency skyter i været, timeout errors | Dynamisk batch sizing (max 500-1000 items for Graph, 10K-100K for OpenAI) |
| **Under-batching** | Ikke utnytter kostnadsbesparelser | Bruk buffering windows (5-10 sek) for å samle requests |
| **Ignorere `custom_id` correlation** | Kan ikke matche responses til opprinnelige requests | Alltid generer UUID eller bruk business ID som `custom_id` |
| **Hardkoding batch file paths** | Konflikter i concurrent jobs | Bruk timestamp eller GUID i filnavn (`batch_20260204_1423_uuid.jsonl`) |
| **Ikke slette output files** | GDPR-brudd (persondata liggende etter processing) | Set `output_expires_after` (14-30 dager) eller slett manuelt post-processing |
| **Blind retry av failed batches** | Cost explosion ved systematic failures | Inspiser failure reasons først, fix underliggende issue, deretter retry |
| **Mixing batch og online i samme deployment** | Quota conflicts, unpredictable performance | Separate deployments for batch vs. online workloads |

### Anbefalinger per Modenhetsnivå

**Level 1 (Proof-of-Concept):**
- Start med Microsoft Graph JSON batching (enkelt, synkron)
- Mål network latency improvement (før/etter batching)
- Max 50-100 requests i første iterasjon

**Level 2 (Pilot):**
- Implementer Azure OpenAI Batch API for ikke-kritiske workloads (rapportering, summarization)
- Kjør side-by-side med online deployment → sammenlign cost og latency
- Etabler monitoring (batch job completion time, failure rate)

**Level 3 (Production):**
- Queue-based batching med Azure Service Bus + Functions
- Auto-scaling compute basert på queue depth
- Exponential backoff retry logic for transient failures
- Dead-letter queue for systematic failures

**Level 4 (Enterprise-Scale):**
- Multi-region batch processing for resilience
- Event-driven orchestration (Event Grid → Logic Apps → Batch API)
- Cost allocation per business unit (tagging av batch jobs)
- FinOps dashboard (cost-per-request tracking, budget alerts)

### Decision Matrix: Batch vs. Online

Bruk denne matrisen for raskt å avgjøre om batching er riktig:

| Kriterium | Batch ✅ | Online ✅ |
|-----------|----------|-----------|
| Latency SLA < 5 sek | ❌ | ✅ |
| Volum > 1000 requests/dag | ✅ | ❌ (dyrere) |
| Budget-begrenset | ✅ (50% rabatt) | ❌ |
| Real-time user interaction | ❌ | ✅ |
| Scheduled/nightly jobs | ✅ | ❌ (waste quota) |
| Personopplysninger uten TIA | ❌ (data residency risk) | ✅ (regional control) |
| Proof-of-concept | 🔶 (start online) | ✅ |
| Production scale | ✅ | 🔶 (hybrid) |

---

## Kilder og Verifisering

### Microsoft Learn (Verified via MCP)

1. **Azure OpenAI Batch API:**
   - [Getting started with Azure OpenAI batch deployments](https://learn.microsoft.com/en-us/azure/ai-foundry/openai/how-to/batch) — **Verified 2026-02**
   - Dekker: JSONL input format, Global-Batch deployment, 50% cost reduction, exponential backoff queuing

2. **Microsoft Graph JSON Batching:**
   - [Combine multiple HTTP requests using JSON batching](https://learn.microsoft.com/en-us/graph/json-batching) — **Verified 2026-02**
   - Dekker: $batch endpoint, request/response correlation, dependsOn sequencing, 20-request limit

3. **Azure Machine Learning Batch Endpoints:**
   - [Batch endpoints](https://learn.microsoft.com/en-us/azure/machine-learning/concept-endpoints-batch?view=azureml-api-2) — **Verified 2026-02**
   - Dekker: Asynchronous inferencing, pipeline component deployments, low-priority VMs, scale-to-zero

4. **Code Samples (Python):**
   - [Azure OpenAI Batch API - Create batch job](https://learn.microsoft.com/en-us/azure/ai-foundry/openai/how-to/batch?pivots=programming-language-python#create-batch-job) — **Verified 2026-02**
   - [Azure Cosmos DB Transactional Batch](https://learn.microsoft.com/en-us/azure/cosmos-db/transactional-batch#how-to-create-a-transactional-batch-operation) — **Baseline (ikke AI-spesifikk, men relevant pattern)**

### Konfidensnivå per Seksjon

| Seksjon | Konfidens | Kilde |
|---------|-----------|-------|
| Azure OpenAI Batch API | **Verified** | Microsoft Learn MCP (2026-02) |
| Microsoft Graph JSON Batching | **Verified** | Microsoft Learn MCP (2026-02) |
| Azure ML Batch Endpoints | **Verified** | Microsoft Learn MCP (2026-02) |
| Prismodell (50% rabatt) | **Verified** | Azure OpenAI pricing page (referenced in docs) |
| NOK conversion | **Baseline** | Modell-kunnskap (indikativ valutakurs) |
| Schrems II implications | **Baseline** | Modell-kunnskap (juridisk interpretasjon) |
| FinOps best practices | **Baseline** | Modell-kunnskap (generell FinOps-prinsipper) |
| Queue-based patterns | **Baseline** | Modell-kunnskap (Azure Functions + Service Bus) |

### Relaterte Ressurser

- [Azure OpenAI pricing](https://azure.microsoft.com/pricing/details/cognitive-services/openai-service/)
- [Azure Machine Learning pricing](https://azure.microsoft.com/pricing/details/machine-learning/)
- [Azure Service Bus pricing](https://azure.microsoft.com/pricing/details/service-bus/)
- [OData $batch specification](http://docs.oasis-open.org/odata/odata-json-format/v4.01/odata-json-format-v4.01.html#sec_BatchRequestsandResponses)

---

**Slutt av Referanse**
