Skill: azd + Terraform Large Deployment Pattern
Problem
When deploying 70+ Azure resources via azd up with Terraform, the deployment can take 10-60+ minutes. Without proper monitoring, it's unclear whether the deployment is progressing, stalled, or failed. Blocking on the command prevents other work and risks timeouts.
Solution
Use async PowerShell execution with periodic polling to monitor long-running deployments non-blockingly.
Deployment Pattern
# Launch deployment in async mode with 2-minute initial wait
azd up --no-prompt
# mode: async, initial_wait: 120, shellId: azd-up-deployment
# Poll periodically (every 5 minutes) to check progress
read_powershell shellId: azd-up-deployment, delay: 300
# Continue until exit code 0 (success) or non-zero (failure)
Key Decisions
- Async Mode: Prevents shell blocking on long-running commands. Allows periodic status checks.
- Initial Wait: 120 seconds to capture startup messages (module upgrades, provider initialization).
- Poll Interval: 300 seconds (5 minutes) balances responsiveness with API overhead.
- No-Prompt Flag:
--no-prompt prevents interactive confirmation prompts that would block async execution.
Timing Expectations (77 Resources Example)
From real deployment (ai-policy-engine-k8m2):
- Total Duration: ~10 minutes (77 resources)
- Provisioning: 9 minutes 8 seconds
- Deploying: 50 seconds
- Longest Pole: Redis Enterprise cluster (6m22s)
- APIM Service: 3-4 minutes
- Container App: 18 seconds (after Redis + Cosmos ready)
- Role Assignments: 20-25 seconds per assignment
Resource Creation Order (Terraform Dependency Graph)
- Foundation (0-2 min): Resource Group, Key Vault, Log Analytics, App Insights, Managed Identity
- Data Layer (2-9 min): Redis Enterprise (longest pole), Cosmos DB
- Compute Layer (7-9 min): Container Apps Environment, Aspire Dashboard, APIM Service
- AI Services (4-6 min): Cognitive Services, AI Services deployment
- Gateway Layer (9-10 min): APIM APIs, Operations, Policies (depends on Container App URL)
- Access Control (9-10 min): Role Assignments, Redis access policies (parallel)
Gotchas
- Redis Enterprise Creation: Budget 7-10 minutes. This is always the longest resource.
- APIM Policy Timing: Policies applied AFTER Container App URL is available (named value dependency). Ensure Container App is created first.
- Parallel Provisioning: azd overlaps packaging with provisioning. API container image builds in parallel with Terraform apply. Efficient by default.
- Exit Code 0 = Success: Only trust exit code. Partial output may look like failure but command is still running.
Validation After Deployment
Check Container App Health:
$url = "https://<container-app-url>/health"
Invoke-WebRequest -Uri $url -Method Get
# Expected: 200 OK, "Healthy"
Check APIM Gateway:
$url = "https://<apim-gateway-url>"
Invoke-WebRequest -Uri $url -Method Get
# Expected: 401/403/404 (gateway enforces auth)
Verify Terraform Outputs:
- Container App URL
- APIM Gateway URL
- Cosmos Endpoint
- Redis Hostname
- Key Vault Name
- Resource Group Name
When to Retry
- Transient Failures: Throttling (429), timeouts (408), service unavailable (503) → Retry once after 5 minutes
- Real Config Issues: Invalid Terraform syntax, RBAC denials, quota limits, policy violations → Fix config, validate with
azd provision --preview, then retry
- Auth Errors: AADSTS codes → Check auth alignment (see azd-terraform-auth-alignment skill)
Files to Commit After Success
Per team decision (2026-05-14T15:54:00Z — "Always validate infra fixes before committing"):
- Commit
azure.yaml and infra/terraform/*.tfvars.json ONLY after successful azd up
- DO NOT commit speculative/unvalidated fixes
- Keeps commit tree clean of bad history
Key Learning
For large Terraform deployments (50+ resources):
- Always use async mode + periodic polling
- Budget 2× the expected provisioning time for safety margin
- Redis Enterprise is always the longest pole in data layer
- Validate endpoints after deployment completes
- Only commit infra files after successful validation
When to Apply
Use this pattern when:
- Deploying 50+ Azure resources
- Using azd + Terraform provider
- Deployment expected to take 10+ minutes
- Need to monitor progress without blocking
- Want to continue other work during deployment
1---2name: azd-terraform-large-deployment3description: Skill: azd + Terraform Large Deployment Pattern4---5# Skill: azd + Terraform Large Deployment Pattern67## Problem89When deploying 70+ Azure resources via `azd up` with Terraform, the deployment can take 10-60+ minutes. Without proper monitoring, it's unclear whether the deployment is progressing, stalled, or failed. Blocking on the command prevents other work and risks timeouts.1011## Solution1213Use async PowerShell execution with periodic polling to monitor long-running deployments non-blockingly.1415### Deployment Pattern1617```powershell18# Launch deployment in async mode with 2-minute initial wait19azd up --no-prompt20# mode: async, initial_wait: 120, shellId: azd-up-deployment2122# Poll periodically (every 5 minutes) to check progress23read_powershell shellId: azd-up-deployment, delay: 3002425# Continue until exit code 0 (success) or non-zero (failure)26```2728### Key Decisions29301. **Async Mode:** Prevents shell blocking on long-running commands. Allows periodic status checks.312. **Initial Wait:** 120 seconds to capture startup messages (module upgrades, provider initialization).323. **Poll Interval:** 300 seconds (5 minutes) balances responsiveness with API overhead.334. **No-Prompt Flag:** `--no-prompt` prevents interactive confirmation prompts that would block async execution.3435### Timing Expectations (77 Resources Example)3637From real deployment (ai-policy-engine-k8m2):38- **Total Duration:** ~10 minutes (77 resources)39 - Provisioning: 9 minutes 8 seconds40 - Deploying: 50 seconds41- **Longest Pole:** Redis Enterprise cluster (6m22s)42- **APIM Service:** 3-4 minutes43- **Container App:** 18 seconds (after Redis + Cosmos ready)44- **Role Assignments:** 20-25 seconds per assignment4546### Resource Creation Order (Terraform Dependency Graph)47481. **Foundation (0-2 min):** Resource Group, Key Vault, Log Analytics, App Insights, Managed Identity492. **Data Layer (2-9 min):** Redis Enterprise (longest pole), Cosmos DB503. **Compute Layer (7-9 min):** Container Apps Environment, Aspire Dashboard, APIM Service514. **AI Services (4-6 min):** Cognitive Services, AI Services deployment525. **Gateway Layer (9-10 min):** APIM APIs, Operations, Policies (depends on Container App URL)536. **Access Control (9-10 min):** Role Assignments, Redis access policies (parallel)5455### Gotchas5657- **Redis Enterprise Creation:** Budget 7-10 minutes. This is always the longest resource.58- **APIM Policy Timing:** Policies applied AFTER Container App URL is available (named value dependency). Ensure Container App is created first.59- **Parallel Provisioning:** azd overlaps packaging with provisioning. API container image builds in parallel with Terraform apply. Efficient by default.60- **Exit Code 0 = Success:** Only trust exit code. Partial output may look like failure but command is still running.6162### Validation After Deployment63641. **Check Container App Health:**65 ```powershell66 $url = "https://<container-app-url>/health"67 Invoke-WebRequest -Uri $url -Method Get68 # Expected: 200 OK, "Healthy"69 ```70712. **Check APIM Gateway:**72 ```powershell73 $url = "https://<apim-gateway-url>"74 Invoke-WebRequest -Uri $url -Method Get75 # Expected: 401/403/404 (gateway enforces auth)76 ```77783. **Verify Terraform Outputs:**79 - Container App URL80 - APIM Gateway URL81 - Cosmos Endpoint82 - Redis Hostname83 - Key Vault Name84 - Resource Group Name8586### When to Retry8788- **Transient Failures:** Throttling (429), timeouts (408), service unavailable (503) → Retry once after 5 minutes89- **Real Config Issues:** Invalid Terraform syntax, RBAC denials, quota limits, policy violations → Fix config, validate with `azd provision --preview`, then retry90- **Auth Errors:** AADSTS codes → Check auth alignment (see azd-terraform-auth-alignment skill)9192### Files to Commit After Success9394Per team decision (2026-05-14T15:54:00Z — "Always validate infra fixes before committing"):95- Commit `azure.yaml` and `infra/terraform/*.tfvars.json` ONLY after successful `azd up`96- DO NOT commit speculative/unvalidated fixes97- Keeps commit tree clean of bad history9899## Key Learning100101For large Terraform deployments (50+ resources):102- Always use async mode + periodic polling103- Budget 2× the expected provisioning time for safety margin104- Redis Enterprise is always the longest pole in data layer105- Validate endpoints after deployment completes106- Only commit infra files after successful validation107108## When to Apply109110Use this pattern when:111- Deploying 50+ Azure resources112- Using azd + Terraform provider113- Deployment expected to take 10+ minutes114- Need to monitor progress without blocking115- Want to continue other work during deployment