| name | azure-terraform-best-practices |
| description | Azure Terraform best practices and deployment preflight workflow. Use when creating, editing, reviewing, validating, or planning infra/**/*.tf, azurerm resources, tfvars environments, Azure Container Apps infrastructure, managed identity, Key Vault, networking, observability, or Terraform deployment readiness. |
Azure Terraform Best Practices
Source: adapted from github/awesome-copilot Azure deployment-preflight guidance and Azure MCP best-practices output, tailored for this Terraform repository.
When to Use
- Creating or editing Terraform under
infra/**/*.tf
- Reviewing environment-specific settings under
infra/environments/*.tfvars
- Preparing a Terraform plan for Azure deployment
- Checking Azure security, reliability, observability, and cost hygiene before merge
Required Context
- Read
.github/copilot-instructions.md for repository-wide Azure and Terraform conventions.
- Read
.github/instructions/terraform.instructions.md before editing infra/**/*.tf.
- Identify the target environment:
dev, uat, or prd.
- Confirm subscription ID is supplied at runtime; do not place it in tfvars or source files.
Terraform Conventions
- Every module must accept
environment as a string variable with a description.
- Every variable and output must include a description.
- Use
terraform fmt formatting with two-space indentation.
- Tag resources with
environment, project = "ghcp-demo", and managed-by = "terraform".
- Keep environment differences in
.tfvars; do not fork modules by environment.
- Never store secrets in
.tfvars. Reference Key Vault or use managed identity patterns.
- Backend state should use Azure Blob Storage with environment-scoped state files.
Azure Best Practices
- Prefer managed identities for app-to-Azure-service access.
- Use least-privilege RBAC scoped to the narrowest practical resource.
- Do not hardcode credentials, connection strings, subscription IDs, or tenant IDs.
- Keep data services private where possible; avoid public PostgreSQL endpoints.
- Do not disable Key Vault purge protection for production resources.
- Do not enable anonymous pull on Container Registry.
- Disable non-TLS Redis access and require modern TLS on Storage and Redis.
- Enable diagnostic settings and route logs/metrics to Log Analytics or Application Insights where the module owns the resource.
- Consider cost impact of SKUs, retention, replica counts, and non-production always-on capacity.
Preflight Workflow
Run from the infra directory unless the user specifies another path.
terraform fmt -recursive -check
terraform init
terraform validate
terraform plan -var-file=environments/dev.tfvars -var="subscription_id=<runtime-subscription-id>" -out=dev.tfplan
terraform show -json dev.tfplan > dev-plan.json
Repeat with uat.tfvars and prd.tfvars when the change affects shared modules or environment-specific behavior.
Review Output
## Azure Terraform Preflight: <environment>
### Commands
- [command]: pass/fail and important output
### Findings
1. [Severity] [file or module]
Finding: ...
Impact: ...
Remediation: ...
### Plan Summary
- Create: X
- Modify: Y
- Destroy: Z
- Replace: N
### Deployment Readiness
- Ready / Ready with notes / Blocked
Escalation
- Use
terraform-azurerm-set-diff-analyzer when a plan shows noisy Set-type diffs.
- Suggest
@architecture-reviewer when a remediation changes the system design.
- Suggest
@adr-generator for non-obvious architecture trade-offs.