Use Terraform with Azure Developer CLI (azd) for Infrastructure
Context and Problem Statement
The CIMPL platform needs an infrastructure-as-code (IaC) tool and deployment orchestrator for provisioning Azure resources and managing deployment lifecycle. The choice of IaC tooling is foundational — it determines provider ecosystem, state management, CI/CD pipeline design, and the developer experience for azd up deployments. The reference CIMPL implementation (cimpl-azd) already uses Terraform with azd, and alignment with that project reduces onboarding friction.
Decision Drivers
- Single-command deployment experience (
azd up/azd down) - Mature provider ecosystem for Azure, Kubernetes, and Helm resources
- Lifecycle hooks for multi-layer orchestration (pre-provision, post-provision, pre-down)
- State management flexibility (local for development, remote for CI/CD)
- Alignment with reference implementation (cimpl-azd) for knowledge transfer
- Team familiarity and existing tooling investment
Considered Options
- Terraform with Azure Developer CLI (azd)
- Bicep with Azure Developer CLI (azd)
- Pulumi with Azure Developer CLI (azd)
- Terraform without azd (standalone CLI)
Decision Outcome
Chosen option: "Terraform with Azure Developer CLI (azd)", because it provides the best combination of mature multi-provider support, lifecycle orchestration, and direct alignment with the reference implementation.
Consequences
- Good, because
azd upprovides a single-command deployment that orchestrates Terraform init, plan, and apply with lifecycle hooks - Good, because Terraform's
azurerm,kubernetes, andhelmproviders allow managing all three deployment layers (infra, platform, software) with one toolchain - Good, because lifecycle hooks (
pre-provision,post-provision,pre-down) enable multi-layer teardown ordering and validation gates - Good, because direct alignment with cimpl-azd reference means ADRs, patterns, and modules can be ported with minimal translation
- Good, because azd manages environment configuration (
.azure/<env>/) and variable injection (main.tfvars.jsonwith${AZURE_*}substitution) - Bad, because Terraform requires explicit state management — local state works for development but remote backend is needed for CI/CD and team collaboration
- Bad, because azd's Terraform integration is less mature than its Bicep integration (fewer azd templates use Terraform)
- Bad, because PowerShell is required for lifecycle hook scripts to maintain cross-platform compatibility with azd
Pros and Cons of the Options
Terraform with Azure Developer CLI (azd)
HashiCorp Terraform orchestrated by Microsoft's Azure Developer CLI for environment and lifecycle management.
- Good, because multi-provider support (azurerm, kubernetes, helm, azapi) covers all deployment layers
- Good, because HCL is widely known and well-documented
- Good, because reference implementation uses identical toolchain
- Good, because azd handles environment isolation and variable injection
- Neutral, because Terraform state must be managed (local or remote backend)
- Bad, because azd + Terraform has fewer community templates than azd + Bicep
Bicep with Azure Developer CLI (azd)
Azure-native IaC language with first-class azd support.
- Good, because first-class azd integration (most azd templates use Bicep)
- Good, because no state file management — ARM handles state
- Good, because Azure-native tooling with direct ARM API compilation
- Bad, because no Kubernetes or Helm provider — cannot manage platform/software layers
- Bad, because would require a second tool (Helm CLI, kubectl) for Kubernetes workloads
- Bad, because no alignment with reference implementation
Pulumi with Azure Developer CLI (azd)
General-purpose IaC using programming languages (TypeScript, Python, Go).
- Good, because real programming language with loops, conditionals, and type safety
- Good, because multi-provider support similar to Terraform
- Bad, because no azd integration — would need custom orchestration
- Bad, because no alignment with reference implementation
- Bad, because smaller community and fewer Azure-specific examples
Terraform without azd (standalone CLI)
Terraform with custom scripts for environment management and deployment orchestration.
- Good, because full control over workflow without azd abstractions
- Good, because no dependency on azd release cadence
- Bad, because must build environment management, variable injection, and lifecycle orchestration from scratch
- Bad, because loses
azd up/azd downsingle-command experience - Bad, because CI/CD pipeline must handle all orchestration that azd provides for free
More Information
- Azure Developer CLI documentation
- azd Terraform support
- Reference implementation: cimpl-azd