Skip to content

ADR-0002: Use Terraform for infrastructure as code

Status

Accepted

Context

Infrastructure needs to be provisioned consistently and reproducibly. Manual Azure portal changes are error-prone and not auditable. The main IaC options considered were:

  • Terraform -- HashiCorp's multi-cloud IaC tool (HCL)
  • Bicep -- Azure-native IaC (ARM template DSL)
  • Pulumi -- IaC using general-purpose programming languages
  • Azure CLI scripts -- Imperative shell scripts

Decision

Use Terraform (version >= 1.6.6) with the azurerm provider (~> 4.60) for all infrastructure provisioning.

Infrastructure is organized as:

terraform/
├── backend/     # State backend bootstrapping (local state)
├── modules/     # Reusable modules (postgres-flex, rbac, resource-group, swa)
└── envs/        # Environment root modules (shared, site)

Consequences

Positive

  • Multi-cloud portability -- If the organization moves to AWS or GCP, Terraform skills and patterns transfer. Modules would need rewriting, but the workflow stays the same.
  • State management -- Terraform tracks resource state, enabling safe plans and applies. Drift detection comes for free.
  • Module system -- Reusable modules (postgres-flex, swa, etc.) reduce duplication across environments.
  • Ecosystem -- Largest IaC ecosystem with extensive provider support and community modules.
  • PR-based workflow -- terraform plan on PRs, terraform apply on merge. Changes are reviewed before applying.

Negative

  • HCL learning curve -- HCL is a domain-specific language, not a general-purpose language. Contributors need to learn it.
  • State file management -- Remote state requires storage accounts and careful access control. State corruption can be difficult to recover from.
  • Provider version management -- Provider updates can introduce breaking changes requiring module updates.

Neutral

  • Terraform is not Azure-native (unlike Bicep), but the azurerm provider covers all services used by this organization.
  • HashiCorp's licensing changes (BSL) don't affect this use case.