# Capacity Planning for DR Configurations

**Last updated:** 2026-02
**Status:** GA
**Category:** Business Continuity & Disaster Recovery

---

## Introduksjon

Kapasitetsplanlegging for Disaster Recovery-konfigurasjoner handler om å dimensjonere reserveressurser riktig slik at AI-systemer kan gjenopprettes innenfor definerte RTO- og RPO-mål. For AI-arbeidsbelastninger er dette spesielt utfordrende fordi ressurskravene er høye (GPU-compute, store indekser, høy throughput) og kostnadene eskalerer raskt ved full duplisering.

Azure tilbyr flere strategier for å balansere kapasitet, kostnad og gjenopprettingstid: fra alltid-aktive active-active konfigurasjoner til minimalt provisionerte warm/cold standby-oppsett med auto-scaling. Valget avhenger av kritikalitetstier og budsjett.

Norske offentlige organisasjoner må gjøre en avveining mellom tilgjengelighetskrav (NSMs grunnprinsipper) og kostnadseffektivitet (krav om forsvarlig bruk av offentlige midler). Kapasitetsplanlegging bør dokumenteres som del av organisasjonens BCDR-plan og revideres minst årlig.

## Dimensjonering av DR-miljø for toppbelastning

### AI-komponent dimensjoneringsmatrise

| AI-komponent | Primær region | DR (Active-Active) | DR (Warm Standby) | DR (Cold Standby) |
|--------------|--------------|--------------------|--------------------|-------------------|
| Azure OpenAI | 120K TPM | 120K TPM | 60K TPM + autoscale | 0 (redeploy) |
| AI Search (replikaer) | 3 | 3 | 2 | 0 (rebuild) |
| AI Search (partisjoner) | 4 | 4 | 4 | 0 (rebuild) |
| App Service | P3v3 x 3 | P3v3 x 3 | P2v3 x 1 | 0 (deploy) |
| Cosmos DB (RU/s) | 10,000 | 10,000 | 4,000 (autoscale) | 0 (restore) |

### Beregning av DR-kapasitetsbehov

```python
# Kapasitetsberegningsmodell for AI DR-miljø
def calculate_dr_capacity(primary_config, dr_strategy, peak_multiplier=1.2):
    """
    Beregn nødvendig DR-kapasitet basert på primær konfigurasjon.

    Args:
        primary_config: Dict med primær region ressurser
        dr_strategy: 'active-active', 'warm-standby', 'cold-standby'
        peak_multiplier: Faktor for toppbelastning (default 1.2x)
    """
    dr_config = {}

    if dr_strategy == "active-active":
        # Full kapasitet i begge regioner
        for resource, capacity in primary_config.items():
            dr_config[resource] = capacity * peak_multiplier

    elif dr_strategy == "warm-standby":
        # Redusert kapasitet, skaleres opp ved failover
        scaling_factors = {
            "openai_tpm": 0.5,        # 50% av primær
            "search_replicas": 0.67,    # 2 av 3 replikaer
            "search_partitions": 1.0,   # Full (kan ikke skalere raskt)
            "app_service_instances": 0.33,  # 1 av 3 instanser
            "cosmos_ru": 0.4,          # 40% med autoscale til 100%
        }
        for resource, capacity in primary_config.items():
            factor = scaling_factors.get(resource, 0.5)
            dr_config[resource] = int(capacity * factor)

    elif dr_strategy == "cold-standby":
        # Ingen kjørende ressurser, kun IaC-maler
        for resource, capacity in primary_config.items():
            dr_config[resource] = 0
        dr_config["iac_templates"] = True
        dr_config["estimated_deploy_time_minutes"] = 30

    return dr_config

# Eksempel
primary = {
    "openai_tpm": 120000,
    "search_replicas": 3,
    "search_partitions": 4,
    "app_service_instances": 3,
    "cosmos_ru": 10000
}

warm = calculate_dr_capacity(primary, "warm-standby")
print(f"Warm standby config: {warm}")
# Output: {'openai_tpm': 60000, 'search_replicas': 2, ...}
```

## Surge capacity og burst-håndtering

### Azure OpenAI Token Rate Limiting

Azure OpenAI har regionalt baserte kvoter. Ved failover til sekundær region kan eksisterende kvoter være utilstrekkelige.

```bash
# Sjekk nåværende kvote i sekundær region
az cognitiveservices account list-usage \
  --name "aoai-secondary-swedencentral" \
  --resource-group "rg-ai-dr" \
  --output table

# Pre-provisioner kapasitet med Provisioned Throughput Units (PTU)
az cognitiveservices account deployment create \
  --name "aoai-secondary-swedencentral" \
  --resource-group "rg-ai-dr" \
  --deployment-name "gpt-4o-ptu" \
  --model-name "gpt-4o" \
  --model-version "2024-08-06" \
  --model-format "OpenAI" \
  --sku-capacity 50 \
  --sku-name "ProvisionedManaged"
```

### Auto-scaling for App Service

```bash
# Konfigurer autoscale i DR-region
az monitor autoscale create \
  --resource-group "rg-ai-dr" \
  --name "autoscale-ai-app-dr" \
  --resource "/subscriptions/{sub}/resourceGroups/rg-ai-dr/providers/Microsoft.Web/serverFarms/asp-ai-dr" \
  --min-count 1 \
  --max-count 5 \
  --count 1

# Scale-up regel basert på CPU
az monitor autoscale rule create \
  --resource-group "rg-ai-dr" \
  --autoscale-name "autoscale-ai-app-dr" \
  --condition "Percentage CPU > 70 avg 5m" \
  --scale out 2

# Scale-down regel
az monitor autoscale rule create \
  --resource-group "rg-ai-dr" \
  --autoscale-name "autoscale-ai-app-dr" \
  --condition "Percentage CPU < 30 avg 10m" \
  --scale in 1
```

### Cosmos DB Autoscale

```bash
# Konfigurer autoscale for Cosmos DB i DR-region
# Baseline: 4000 RU/s, maks: 10000 RU/s
az cosmosdb sql container throughput migrate \
  --account-name "cosmos-ai-dr" \
  --resource-group "rg-ai-dr" \
  --database-name "chatbot-state" \
  --name "conversations" \
  --throughput-type "autoscale"

az cosmosdb sql container throughput update \
  --account-name "cosmos-ai-dr" \
  --resource-group "rg-ai-dr" \
  --database-name "chatbot-state" \
  --name "conversations" \
  --max-throughput 10000
```

## Kostnadsoptimalisering for standby-ressurser

### Kostnadsprofiler per DR-strategi

| Strategi | Kostnad vs. primær | RTO | Best for |
|----------|-------------------|-----|----------|
| Active-Active (full) | 100% | ~0 | Tier 0: Mission Critical |
| Active-Active (optimized autoscale) | 50–70% | Sekunder | Tier 0/1 |
| Warm Standby (partial) | 25–40% | 5–15 min | Tier 1: Business Critical |
| Cold Standby (IaC only) | 5–10% | 30–60 min | Tier 2: Business Operational |
| Backup & Restore | 2–5% | Timer–Dager | Tier 3: Administrative |

### Spesifikke kostnadsbesparelser

```markdown
## Kostnadsbesparelser for Warm Standby

1. **Azure OpenAI**: Bruk pay-per-token (ikke PTU) i DR-region
   - Besparelse: 60–80% vs. PTU
   - Tradeoff: Ingen garantert kapasitet ved failover

2. **AI Search**: 2 replikaer i stedet for 3 i DR
   - Besparelse: ~33% på search-kostnaden
   - Tradeoff: 99.9% SLA i stedet for 99.99%

3. **App Service**: P2v3 i stedet for P3v3, med autoscale
   - Besparelse: ~50% på compute
   - Tradeoff: 1–2 min skaleringstid ved failover

4. **Cosmos DB**: Autoscale med lav baseline
   - Besparelse: 40–60% ved lavt normalbruk
   - Tradeoff: Opptil 10s oppskaleringsforsinkelse
```

### Azure Cost Management for DR

```bash
# Tag alle DR-ressurser for kostnadssporing
az tag create --name "Environment" --value "DR"

# Sett budsjett-alert for DR-ressursgruppe
az consumption budget create \
  --budget-name "dr-monthly-budget" \
  --amount 50000 \
  --category "Cost" \
  --time-grain "Monthly" \
  --time-period '{"Start": "2026-01-01", "End": "2026-12-31"}' \
  --resource-groups "rg-ai-dr" \
  --notifications '{
    "Warning80": {
      "enabled": true,
      "operator": "GreaterThan",
      "threshold": 80,
      "contactEmails": ["platform-team@org.no"]
    },
    "Critical100": {
      "enabled": true,
      "operator": "GreaterThan",
      "threshold": 100,
      "contactEmails": ["platform-team@org.no", "management@org.no"]
    }
  }'
```

## Skaleringsregler og auto-scaling

### DR Activation Scaling Pipeline

```yaml
# Azure DevOps Pipeline: DR Activation Scale-Up
trigger: none  # Manuelt eller via alert webhook

parameters:
  - name: activationType
    type: string
    values:
      - failover
      - failover-drill
      - scale-test

stages:
  - stage: ScaleUpDR
    displayName: 'Scale Up DR Environment'
    jobs:
      - job: ScaleSearchService
        steps:
          - task: AzureCLI@2
            displayName: 'Scale AI Search to 3 replicas'
            inputs:
              azureSubscription: 'dr-service-connection'
              scriptType: 'bash'
              scriptLocation: 'inlineScript'
              inlineScript: |
                az search service update \
                  --name "search-secondary-swedencentral" \
                  --resource-group "rg-ai-dr" \
                  --replica-count 3

      - job: ScaleAppService
        steps:
          - task: AzureCLI@2
            displayName: 'Scale App Service to P3v3'
            inputs:
              azureSubscription: 'dr-service-connection'
              scriptType: 'bash'
              scriptLocation: 'inlineScript'
              inlineScript: |
                az appservice plan update \
                  --name "asp-ai-dr" \
                  --resource-group "rg-ai-dr" \
                  --sku P3v3

      - job: VerifyCapacity
        dependsOn:
          - ScaleSearchService
          - ScaleAppService
        steps:
          - task: AzureCLI@2
            displayName: 'Verify DR capacity'
            inputs:
              azureSubscription: 'dr-service-connection'
              scriptType: 'bash'
              scriptLocation: 'inlineScript'
              inlineScript: |
                echo "=== Search Service ==="
                az search service show \
                  --name "search-secondary-swedencentral" \
                  --resource-group "rg-ai-dr" \
                  --query "{replicas:replicaCount, partitions:partitionCount, status:status}"

                echo "=== App Service Plan ==="
                az appservice plan show \
                  --name "asp-ai-dr" \
                  --resource-group "rg-ai-dr" \
                  --query "{sku:sku.name, workers:numberOfWorkers}"
```

## Kapasitetsreservasjonsstrategier

### Azure Reserved Instances for DR

| Ressurstype | Reservasjonsanbefaling | Besparelse | Merknad |
|-------------|----------------------|------------|---------|
| App Service P2v3 | 1-år RI for baseline | ~35% | For warm standby baseline |
| Cosmos DB (autoscale) | Ingen RI | N/A | Autoscale er per-bruk |
| Azure OpenAI PTU | RI kun for primær | ~30% | DR bruker pay-per-token |
| AI Search Standard | RI for begge regioner | ~35% | Partisjoner kjører alltid |
| Storage (GZRS) | Reservert kapasitet | ~25% | For store datasett |

### Capacity Reservation Groups

```bash
# Opprett kapasitetsreservasjon for VM-baserte workloads i DR-region
az capacity reservation group create \
  --name "crg-ai-dr-swedencentral" \
  --resource-group "rg-ai-dr" \
  --location "swedencentral" \
  --zones 1 2 3

# Reserver spesifikk VM-størrelse
az capacity reservation create \
  --capacity-reservation-group "crg-ai-dr-swedencentral" \
  --resource-group "rg-ai-dr" \
  --name "cr-gpu-nc24ads" \
  --location "swedencentral" \
  --sku "Standard_NC24ads_A100_v4" \
  --capacity 2 \
  --zone 1
```

## Referanser

- [Develop a disaster recovery plan — Optimize your recovery costs](https://learn.microsoft.com/en-us/azure/well-architected/design-guides/disaster-recovery#optimize-your-recovery-costs) — Kostnadsoptimalisering per tier
- [Recovery strategy for active-passive (warm standby)](https://learn.microsoft.com/en-us/azure/well-architected/design-guides/disaster-recovery#recovery-strategy-for-active-passive-warm-standby) — Warm standby konfigurasjon
- [Recovery strategy for active-active deployments](https://learn.microsoft.com/en-us/azure/well-architected/design-guides/disaster-recovery#recovery-strategy-for-active-active-deployments) — Active-active konfigurasjon
- [BCDR considerations with Azure OpenAI](https://learn.microsoft.com/en-us/azure/ai-foundry/openai/how-to/business-continuity-disaster-recovery) — OpenAI-spesifikk kapasitetsplanlegging
- [Management recommendations for AI workloads on Azure IaaS](https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/scenarios/ai/infrastructure/management) — AI-workload management
- [Azure Site Recovery — Plan capacity and scaling](https://learn.microsoft.com/en-us/azure/site-recovery/site-recovery-plan-capacity-vmware) — Kapasitetsplanlegging

## For Cosmo

- **Bruk denne referansen** når kunden trenger hjelp med å dimensjonere og kostnadsoptimalisere sine DR-miljøer for AI-workloads.
- Warm standby med autoscale er den mest kostnadseffektive strategien for Tier 1 (Business Critical) AI-systemer — typisk 25–40% av full dupliseringskostnad.
- Påminn om at Azure OpenAI-kvoter er regionsspesifikke — kunden MÅ pre-allokere kapasitet i DR-regionen, ellers risikerer de at failover feiler pga. kvotebegrensninger.
- For AI Search: Partisjoner kan ikke skaleres ned uten å gjenopprette tjenesten, så dimensjonér partisjoner identisk i begge regioner.
- Anbefal Azure Cost Management med tags og budsjetter for å overvåke DR-kostnader separat fra produksjonskostnader.
