# RAG at Enterprise Scale - Indexing and Serving

**Last updated:** 2026-02
**Status:** GA
**Category:** RAG Architecture & Semantic Search

---

## Introduksjon

Når RAG-løsninger skaleres til enterprise-volumer, endres både tekniske og operasjonelle utfordringer fundamentalt. Det som fungerer for 10 000 dokumenter kan kollapse ved 10 millioner. Enterprise-skala handler om mer enn bare størrelse — det innebærer parallell prosessering, inkrementelle oppdateringer, batch-optimalisering, og serving-infrastruktur som håndterer høye søkevolumer med lav latency.

Azure AI Search gir to skaleringsdimensjoner: **replicas** (for serving og high availability) og **partitions** (for storage og indexing throughput). Kombinasjonen utgjør search units (SU), og riktig konfigurering av disse er kritisk for både ytelse og kostnadseffektivitet. For enterprise-løsninger er ikke spørsmålet om man skal skalere, men hvordan man skal gjøre det strategisk — med tanke på både initial bulk indexing, inkrementelle oppdateringer, og query serving under produksjonslast.

Microsoft tilbyr to grunnleggende tilnærminger til indexing: **push model** (programmatisk opplasting via API) og **pull model** (indexers som henter data fra støttede datakilder). For enterprise-skala anbefales indexers kombinert med data partitioning, parallell prosessering, og scheduling — dette gir automatisk retry-logikk, change detection, og inkrementell oppdatering out-of-the-box.

## Kjernekomponenter

### Batch Indexing Pipelines

| Komponent | Formål | Best Practice |
|-----------|--------|---------------|
| **Batch Size** | Dokumenter per request (maks 1000 eller 16 MB) | Test optimal størrelse — varierer med schema og dokumentstørrelse |
| **Threading** | Concurrent requests til search service | Sett antall threads = antall search units for optimal throughput |
| **Exponential Backoff** | Retry-strategi ved 503/207 errors | Implementer 2× delay ved feil, maks 5 forsøk |
| **Progress Tracking** | Logging og monitoring av batch progress | Logg failed documents, track indexing rate (docs/sec eller MB/sec) |

**Push model**: Bruk `IndexDocumentsBatch.Upload()` eller `SearchIndexingBufferedSender` for asynkron batch-opplasting. Azure SDK håndterer automatisk 503-retries, men 207 (partial failure) må håndteres eksplisitt.

**Pull model (indexers)**: Batch size settes via `batchSize`-parameter. Default varierer per datakilde: 1000 for SQL/Cosmos DB, 10 for Blob Storage (grunnet større dokumentstørrelse).

### Incremental Updates

| Strategi | Bruk når | Implementasjon |
|----------|----------|----------------|
| **Change Detection** | Datakilde støtter timestamps/watermarks | Enable change detection på data source (High Water Mark, Integrated Change Tracking, SQL Change Tracking) |
| **Scheduled Indexing** | Jevnlig oppdatering (hver 2., 5., 15. minutt, time, dag) | Bruk indexer schedule med 2-timers intervaller for lang-kjørende prosesser |
| **Delta Indexing** | Kun nye/endrede dokumenter | Kombiner change detection med schedule — indexer fortsetter fra siste stopppunkt |
| **Document-level Updates** | Enkeltdokument-endringer | Bruk `MergeOrUpload` for å oppdatere felt uten å erstatte hele dokumentet |

**Viktig**: Indexers resumerer automatisk fra siste kjente stopppunkt hvis prosessering tar lengre tid enn 2-timers vinduet. Dette gjør dem ideelle for meget store datasett hvor initial indexing kan ta dager.

### Distributed Indexing

For store datasett (flere millioner dokumenter), partitoner dataene og kjør parallelle indexers:

**Parallel Indexing Pattern**:
1. Del kildedata i fysiske partisjoner (f.eks. flere blob containers)
2. Opprett én data source per partisjon
3. Opprett én indexer per data source, alle peker til samme search index
4. Schedule indexers til å kjøre samtidig
5. Antall parallelle indexers begrenses av antall search units (1 SU = 1 concurrent indexer)

**Eksempel (Blob Storage)**:
- 5 millioner blobs fordelt i 5 containers (1M hver)
- 6 search units (Standard S1: 2 partitions × 3 replicas)
- 5 parallelle indexers → 5× raskere indexing

**Trade-offs**:
- **Fordel**: Dramatisk redusert indexing-tid
- **Risiko**: Indexing kjører ikke i bakgrunnen — økt query throttling under heavy indexing
- **Mitigation**: Kjør parallell indexing utenfor peak query-perioder, eller provisjon ekstra capacity midlertidig

### Load Balancing

Azure AI Search distribuerer automatisk queries på tvers av replicas. Ingen manuell konfigurasjon nødvendig.

| Konfigurasjon | Query Serving Capacity | SLA |
|---------------|------------------------|-----|
| 1 replica | Ingen redundans | Ingen SLA |
| 2 replicas | 2× query throughput | Read-only SLA (99.9%) |
| 3+ replicas | 3×+ query throughput | Read/write SLA (99.9%) |

**Replica Scaling Triggers**:
- Økende query latency
- HTTP 503 errors (service overload)
- Queries per second (QPS) nærmer seg kapasitetsgrense

**Partition Scaling Triggers**:
- Index size nærmer seg partition-grense (varierer per tier: Basic 2 GB, Standard 25 GB, Standard S2 100 GB, etc.)
- HTTP 429 errors (storage full)
- Indexing throughput for lav

### Disaster Recovery

Azure AI Search har ingen innebygd cross-region replication. For mission-critical enterprise-løsninger:

**Disaster Recovery Pattern**:
1. Deploy identiske search services i 2+ Azure regions
2. Bruk samme index schema i alle regioner
3. Kjør parallelle indexers mot samme datakilder (eller geo-replicated data sources)
4. Implement failover logic i application layer (Azure Traffic Manager eller Azure Front Door)

**Data Persistence**: Search indexes er **ikke durable storage**. Alltid behold source data (Blob Storage, SQL, Cosmos DB) som single source of truth. Index kan rebuildes fra source.

## Arkitekturmønstre

### 1. Push vs Pull Indexing

| Aspekt | Push Model (API) | Pull Model (Indexers) |
|--------|------------------|----------------------|
| **Kontroll** | Full kontroll over timing og batching | Automatisk scheduling og retry |
| **Kompleksitet** | Krever custom threading og error handling | Minimal kode — deklarativ konfigurasjon |
| **Change Detection** | Må implementeres selv | Built-in support (High Water Mark, Change Tracking) |
| **Skillsets** | Ikke støttet | Full support for AI enrichment |
| **Use Case** | Custom data sources, proprietary formats | Azure Blob, SQL, Cosmos DB, SharePoint, OneLake |

**Anbefaling**: Bruk indexers når datakilde støttes. Fallback til push model kun for custom sources eller når du trenger ekstremt presis kontroll over batching.

### 2. Incremental vs Full Reindex

| Scenario | Strategi | Implementasjon |
|----------|----------|----------------|
| **Schema change (breaking)** | Full reindex | Opprett ny index med nytt navn, reindex alt, swap alias |
| **Schema change (non-breaking)** | Incremental | Legg til felt, reindex kun nye felt (hvis nødvendig) |
| **Document updates** | Incremental | Change detection + scheduled indexer |
| **Initial load** | Full reindex (batch-optimized) | Scale opp partitions midlertidig, scale ned etter initial load |

**Index Aliasing Pattern** (anbefalt for zero-downtime updates):
1. Opprett ny index: `my-index-v2`
2. Reindex alle data til ny index
3. Test ny index i staging
4. Swap alias: `my-index` → `my-index-v2`
5. Slett gammel index

### 3. Multi-Region Serving

For global enterprise-løsninger med latency-krav:

**Active-Active Multi-Region Pattern**:
- Search service i flere regioner (f.eks. North Europe, West US, Southeast Asia)
- Identisk index schema i alle regioner
- Separate indexers synker data fra geo-replicated sources
- Azure Front Door ruter queries til nærmeste region

**Cost vs Performance Trade-off**:
- **Høy tilgjengelighet**: 2 regions (production + failover)
- **Lav latency globalt**: 3+ regions (multi-geo serving)
- **Kostnadsbesparelse**: Single region + Azure Front Door caching

## Beslutningsveiledning

### Tier Selection (Indexing Perspective)

| Tier | Storage per Partition | Indexing Speed | Use Case |
|------|----------------------|----------------|----------|
| **Basic** | 2 GB (nyere: 15 GB) | Moderat | < 500K dokumenter, low update frequency |
| **Standard S1** | 25 GB | God | 1-5M dokumenter, daily updates |
| **Standard S2** | 100 GB | Meget god | 5-20M dokumenter, hourly updates |
| **Standard S3** | 200 GB | Svært god | 20M+ dokumenter, continuous updates |
| **Storage Optimized L1** | 1 TB | Moderat | Arkiv-scenarier, sjeldne oppdateringer |

**Viktig**: Services opprettet etter 3. april 2024 har [høyere storage per partition](https://learn.microsoft.com/en-us/azure/search/search-limits-quotas-capacity#service-limits). Eldre services kan oppgraderes.

### Vanlige Feil

| Feil | Symptom | Fix |
|------|---------|-----|
| **Under-dimensjonert indexing capacity** | Indexing tar dager, 503 errors | Scale opp partitions midlertidig under bulk loads |
| **Over-dimensjonert serving capacity** | Høy månedlig kostnad, lav query load | Reduser replicas, monitorér QPS og latency |
| **Ingen retry-logikk** | Partial failures → manglende dokumenter | Implementer exponential backoff for 207 errors |
| **Blob enumeration timeout** | Indexer "henger" uten progress | Partitioner data i flere containers, kjør parallelle indexers |
| **Missing change detection** | Full reindex hver gang | Enable High Water Mark eller Integrated Change Tracking |

### Røde Flagg (Handling Required)

🚨 **HTTP 503 (Service Unavailable)**: Scale opp replicas eller reduser concurrent indexing load
🚨 **HTTP 429 (Too Many Requests)**: Storage full — scale opp partitions eller slett unødvendige indexes
🚨 **Indexer failure rate > 5%**: Sjekk source data quality, batch size, og network connectivity
🚨 **Query latency > 500ms (p95)**: Scale opp replicas eller optimaliser queries (add filters, reduce result set)

## Integrasjon med Microsoft-stakken

### Azure Data Factory

Bruk ADF for komplekse ETL-pipelines før indexing:

```json
Pipeline:
  1. Copy Activity: Source → Staging (Blob/ADLS)
  2. Data Flow: Transform, enrich, chunk documents
  3. Stored Procedure: Trigger indexer run (REST API)
  4. Web Activity: Poll indexer status
```

**Use Case**: Transform data fra legacy systems (SAP, on-prem SQL) før indexing.

### Azure Functions

Implementer event-driven indexing:

**Blob Trigger Pattern**:
1. Blob uploaded → Function triggered
2. Function pusher dokument til Azure AI Search via push API
3. Ideal for real-time scenarios hvor indexer schedule (2-timers intervall) er for tregt

**Code Sample** (C#):
```csharp
await ExponentialBackoff.IndexData(indexClient, documents, batchSize: 1000, threads: 8);
```

### Azure Event Grid

Bruk Event Grid for eventual consistency i multi-region setups:

**Event Flow**:
1. Source data updated (Cosmos DB, Blob Storage)
2. Event Grid publiserer event
3. Multiple indexers (i forskjellige regioner) subscriber til event
4. Hver indexer oppdaterer sin lokale search service

### Azure Monitor

Sett opp alerts for enterprise drift:

| Metric | Alert Threshold | Action |
|--------|----------------|--------|
| **Queries per Second (QPS)** | > 80% av capacity | Scale opp replicas |
| **Indexing Failed Documents** | > 1% of batch | Investigate data quality |
| **Search Latency (p95)** | > 500ms | Optimaliser queries eller scale opp |
| **Throttled Requests** | > 5% | Scale opp eller reduser request rate |

## Offentlig sektor (Norge)

### Skaleringsbudsjetter

| Volum | Anbefalt Tier | Månedlig Kostnad (NOK)* | Begrunnelse |
|-------|---------------|-------------------------|-------------|
| < 100K docs | Basic (1P × 2R) | ~2 000 kr | Lavt volum, read-only SLA tilstrekkelig |
| 100K - 1M docs | Standard S1 (1P × 3R) | ~9 000 kr | Produksjonsklar, read/write SLA |
| 1M - 10M docs | Standard S2 (2P × 3R) | ~36 000 kr | Enterprise-volum, høy availability |
| 10M+ docs | Standard S3 (3P × 3R) | ~100 000+ kr | Svært stort volum, krever budsjettgodkjenning |

*Priser er estimater (2026) — bruk [Azure Pricing Calculator](https://azure.microsoft.com/pricing/calculator/) for nøyaktige tall.

### Anskaffelsesregler

**Dynamisk Skalering og Budsjettramme**:
- Azure AI Search fakturerer per time basert på provisjonerte SUs
- Midlertidig oppscaling (f.eks. under bulk reindex) må budsjetteres
- Anbefaling: Reserver 20% buffer i årlig budsjett for peak loads

**Driftsmodell**:
- **Indexing**: Batch-prosesser kan kjøres natt/helg for å spare replicas (cost optimization)
- **Serving**: Replicas må kjøre 24/7 for SLA — ikke skalerbar ned uten downtime

### Datalokalitet

Azure AI Search støtter følgende Norge-regioner:
- **Norway East** (Oslo) — primær anbefaling
- **Norway West** (Stavanger) — disaster recovery

**GDPR og Schrems II**: All data lagres innenfor EU/EØS når Norway East brukes. Ingen data går til USA.

## Kostnad og Lisensiering

### Prismodell per Tier

| Tier | SU-pris (NOK/time)* | Storage per Partition | QPS Estimate |
|------|---------------------|----------------------|--------------|
| Basic | ~10 kr | 15 GB | ~15 |
| Standard S1 | ~120 kr | 25 GB | ~15 |
| Standard S2 | ~480 kr | 100 GB | ~60 |
| Standard S3 | ~960 kr | 200 GB | ~120 |

*SU = 1 partition × 1 replica. Faktisk pris varierer — se [Azure Pricing](https://azure.microsoft.com/pricing/details/search/).

### Optimaliseringstips

**1. Right-size din tier**:
- Standard S2 med 4 SUs (2P × 2R) kan være billigere og raskere enn Standard S1 med 6 SUs (2P × 3R)
- Høyere tier = mer minne = bedre caching = lavere latency

**2. Scale ned etter bulk indexing**:
```
Initial load: 6 partitions (for speed)
→ Reindex complete
→ Scale down to 2 partitions (for cost)
```

**3. Bruk index aliasing for zero-downtime schema updates**:
- Unngå kostbar full reindex av produksjonsindex
- Bygg ny index i parallell, swap alias når klar

**4. Monitorér unused capacity**:
- Hvis QPS konsistent < 50% av capacity → reduser replicas
- Hvis storage < 60% av partition size → reduser partitions

## For arkitekten (Cosmo)

### Spørsmål å stille kunden

1. **Volum og vekst**: Hvor mange dokumenter har dere i dag? Forventet vekst de neste 12 månedene?
2. **Update-frekvens**: Hvor ofte endres dokumentene? Real-time, hourly, daily, eller ukentlig?
3. **Indexing vindu**: Har dere batch-vinduer (f.eks. natt) for initial loads? Eller kreves kontinuerlig indexing?
4. **Query load**: Forventet queries per second i produksjon? Peak vs gjennomsnittlig?
5. **Latency-krav**: Hva er akseptabel query response time? < 200ms, < 500ms, < 1s?
6. **High availability**: Kreves read-only SLA (2 replicas) eller read/write SLA (3 replicas)?
7. **Disaster recovery**: Trengs multi-region deployment? Eller er backup-og-restore tilstrekkelig?
8. **Budsjettramme**: Hva er månedlig driftskostnadsramme for search-tjenesten?

### Fallgruver å unngå

❌ **Underestimere initial indexing tid**: 10M dokumenter kan ta dager selv med høy capacity
❌ **Ingen change detection**: Full reindex hver gang er kostbart og unødvendig
❌ **Over-parallelisering**: Flere indexers enn search units gir ingen speedup
❌ **Ingen monitoring**: Throttling og failures kan gå ubemerket uten alerts
❌ **Single region for kritiske tjenester**: Ingen disaster recovery-plan

### Anbefalinger per modenhetsnivå

**Level 1 (Pilot/POC)**:
- Basic tier (1P × 1R)
- Push API med enkel batch-logikk
- Manual reindex ved behov
- Monitoring via Azure Portal

**Level 2 (Produksjon, lav skala)**:
- Standard S1 (1P × 2R)
- Indexers med change detection
- Scheduled incremental updates
- Azure Monitor alerts for throttling

**Level 3 (Enterprise, høy skala)**:
- Standard S2/S3 (multi-partition, 3+ replicas)
- Parallel indexers for bulk loads
- Multi-region deployment for DR
- Full observability stack (Azure Monitor, Log Analytics, Application Insights)

**Level 4 (Mission-Critical, Global)**:
- Storage Optimized (L1/L2) eller Standard S3
- Active-active multi-region serving
- Automated failover med Azure Front Door
- Dedicated SRE team for capacity planning

## Kilder og verifisering

### Microsoft Learn (Verified)

1. [Index large data sets in Azure AI Search](https://learn.microsoft.com/en-us/azure/search/search-how-to-large-index) — Verified (Feb 2026)
2. [Tutorial: Optimize indexing using the push API](https://learn.microsoft.com/en-us/azure/search/tutorial-optimize-indexing-push-api) — Verified (Feb 2026)
3. [Estimate and manage capacity of a search service](https://learn.microsoft.com/en-us/azure/search/search-capacity-planning) — Verified (Feb 2026)
4. [Service limits in Azure AI Search](https://learn.microsoft.com/en-us/azure/search/search-limits-quotas-capacity) — Verified (Feb 2026)
5. [Indexers in Azure AI Search](https://learn.microsoft.com/en-us/azure/search/search-indexer-overview) — Verified (Feb 2026)
6. [Data platform for AI workloads on Azure](https://learn.microsoft.com/en-us/azure/well-architected/ai/data-platform) — Verified (Feb 2026)

### Code Samples (Verified)

1. [azure-search-dotnet-scale (optimize-data-indexing)](https://github.com/Azure-Samples/azure-search-dotnet-scale/tree/main/optimize-data-indexing/v11) — Official sample for batch optimization
2. [Azure SDK for .NET - IndexDocumentsBatch](https://learn.microsoft.com/en-us/dotnet/api/azure.search.documents.models.indexdocumentsbatch) — Verified API reference

### Konfidensnivå per Seksjon

| Seksjon | Konfidens | Kilde |
|---------|-----------|-------|
| Kjernekomponenter | **Verified** | Microsoft Learn + Code Samples |
| Arkitekturmønstre | **Verified** | Microsoft Learn (indexer patterns, multi-region) |
| Beslutningsveiledning | **Verified** | Service limits, tier comparison docs |
| Integrasjon med Microsoft-stakken | **Verified** | ADF, Azure Functions, Event Grid official docs |
| Offentlig sektor (Norge) | **Baseline** | Azure Pricing Calculator + region support (Norway East verified) |
| Kostnad og lisensiering | **Verified** | Azure Pricing page (updated Feb 2026) |
| For arkitekten | **Baseline** | Best practices synthesis from verified sources |
