Terraform Best Practices
Expert guidance for building production-grade Terraform infrastructure with enterprise patterns for module design, state management, security, testing, and multi-environment deployments.
When to Use This Skill
- Writing reusable Terraform modules for teams or organizations
- Setting up secure remote state management and backend configuration
- Designing multi-environment infrastructure (dev/staging/prod)
- Implementing infrastructure CI/CD pipelines with automated validation
- Managing infrastructure at scale across multiple teams or projects
- Migrating from manual infrastructure to infrastructure-as-code
- Refactoring existing Terraform for better maintainability
- Implementing security best practices for infrastructure code
Core Concepts
Module Design Philosophy
- Composition over monoliths: Break infrastructure into reusable child modules
- Standard structure: main.tf, variables.tf, outputs.tf, versions.tf, README.md
- Type constraints: Use validation blocks and complex types for safety
- Dynamic blocks: Enable flexible configuration without duplication
State Management Principles
- Remote backends: S3+DynamoDB or Terraform Cloud for team collaboration
- State encryption: KMS encryption at rest and in transit (mandatory)
- State locking: Prevent concurrent modifications with DynamoDB
- Workspace strategy: Directory-based for production, workspaces for similar envs
Security Fundamentals
- Secret management: AWS Secrets Manager, HashiCorp Vault (never hardcode)
- Least privilege: Separate IAM roles per environment
- Security scanning: tfsec, Checkov, Terrascan in CI/CD
- Resource tagging: Enable cost tracking, ownership, compliance
Testing & Validation
- Pre-commit hooks: Format, validate, lint before commits
- Plan review: Always save and review plans before apply
- Automated testing: Terratest for critical infrastructure modules
- Policy as code: OPA/Sentinel for compliance enforcement
Quick Reference
| Task |
Load reference |
| Module structure, variables, outputs, dynamic blocks |
skills/terraform-best-practices/references/module-design.md |
| Remote backends, state encryption, workspace strategies |
skills/terraform-best-practices/references/state-management.md |
| Variable precedence, tfvars, Terragrunt DRY config |
skills/terraform-best-practices/references/environment-management.md |
| Secrets, IAM, scanning tools, resource tagging |
skills/terraform-best-practices/references/security.md |
| Pre-commit hooks, Terratest, policy as code |
skills/terraform-best-practices/references/testing-validation.md |
| Comprehensive checklist for all areas |
skills/terraform-best-practices/references/best-practices-summary.md |
Workflow
1. Project Setup
# Initialize directory structure
mkdir -p {modules,environments/{dev,staging,prod}}
# Set up remote backend (bootstrap S3 + DynamoDB first)
# Configure backend.tf with encryption and locking
2. Module Development
# Create module with standard structure
cd modules/my-module
touch main.tf variables.tf outputs.tf versions.tf README.md
# Add validation to variables
# Use complex types for structured inputs
# Document outputs with descriptions
3. Security Hardening
# Mark sensitive variables
# Use secret management for credentials
# Configure state encryption
# Set up security scanning in CI/CD
4. Testing Pipeline
# Install pre-commit hooks
pre-commit install
# Run validation locally
terraform init
terraform validate
terraform fmt -check
# Security scanning
tfsec .
checkov -d .
# Automated tests (critical modules)
cd tests && go test -v
5. Deployment Process
# Plan with output file
terraform plan -out=tfplan
# Review plan thoroughly
terraform show tfplan
# Apply only after approval
terraform apply tfplan
# Verify deployment
terraform output
6. Multi-Environment Management
# Use directory-based isolation for production
cd environments/prod
terraform init
terraform workspace list
# Or use Terragrunt for DRY backend config
terragrunt plan
Common Mistakes
❌ Hardcoding secrets in code → Use secret management services
❌ No state locking → Enable DynamoDB locking to prevent conflicts
❌ Skipping plan review → Always save and review execution plans
❌ No version constraints → Pin provider and module versions
❌ Local state in teams → Use remote backends for collaboration
❌ No security scanning → Integrate tfsec/Checkov in CI/CD
❌ Missing resource tags → Tag all resources for cost/ownership tracking
❌ No automated testing → Write Terratest for critical modules
❌ Monolithic modules → Break into composable child modules
❌ No backup strategy → Enable S3 versioning on state buckets
Resources
1---
2name: terraform-best-practices
3description: Terraform infrastructure-as-code best practices for scalable and maintainable cloud infrastructure. Use when writing Terraform modules, managing infrastructure state, or implementing infrastructure automation at scale.
4keywords:
5 - HCL
6 - IaC
7 - infrastructure as code
8 - infrastructure automation
9 - remote state
10 - state management
11 - terraform
12 - terraform module
13 - terraform workspace
14 - terragrunt
15file_patterns:
16 - '**/*.tf'
17 - '**/terraform/**'
18confidence: 0.9
19---
20
21# Terraform Best Practices
22
23Expert guidance for building production-grade Terraform infrastructure with enterprise patterns for module design, state management, security, testing, and multi-environment deployments.
24
25## When to Use This Skill
26
27- Writing reusable Terraform modules for teams or organizations
28- Setting up secure remote state management and backend configuration
29- Designing multi-environment infrastructure (dev/staging/prod)
30- Implementing infrastructure CI/CD pipelines with automated validation
31- Managing infrastructure at scale across multiple teams or projects
32- Migrating from manual infrastructure to infrastructure-as-code
33- Refactoring existing Terraform for better maintainability
34- Implementing security best practices for infrastructure code
35
36## Core Concepts
37
38### Module Design Philosophy
39- **Composition over monoliths**: Break infrastructure into reusable child modules
40- **Standard structure**: main.tf, variables.tf, outputs.tf, versions.tf, README.md
41- **Type constraints**: Use validation blocks and complex types for safety
42- **Dynamic blocks**: Enable flexible configuration without duplication
43
44### State Management Principles
45- **Remote backends**: S3+DynamoDB or Terraform Cloud for team collaboration
46- **State encryption**: KMS encryption at rest and in transit (mandatory)
47- **State locking**: Prevent concurrent modifications with DynamoDB
48- **Workspace strategy**: Directory-based for production, workspaces for similar envs
49
50### Security Fundamentals
51- **Secret management**: AWS Secrets Manager, HashiCorp Vault (never hardcode)
52- **Least privilege**: Separate IAM roles per environment
53- **Security scanning**: tfsec, Checkov, Terrascan in CI/CD
54- **Resource tagging**: Enable cost tracking, ownership, compliance
55
56### Testing & Validation
57- **Pre-commit hooks**: Format, validate, lint before commits
58- **Plan review**: Always save and review plans before apply
59- **Automated testing**: Terratest for critical infrastructure modules
60- **Policy as code**: OPA/Sentinel for compliance enforcement
61
62## Quick Reference
63
64| Task | Load reference |
65| --- | --- |
66| Module structure, variables, outputs, dynamic blocks | `skills/terraform-best-practices/references/module-design.md` |
67| Remote backends, state encryption, workspace strategies | `skills/terraform-best-practices/references/state-management.md` |
68| Variable precedence, tfvars, Terragrunt DRY config | `skills/terraform-best-practices/references/environment-management.md` |
69| Secrets, IAM, scanning tools, resource tagging | `skills/terraform-best-practices/references/security.md` |
70| Pre-commit hooks, Terratest, policy as code | `skills/terraform-best-practices/references/testing-validation.md` |
71| Comprehensive checklist for all areas | `skills/terraform-best-practices/references/best-practices-summary.md` |
72
73## Workflow
74
75### 1. Project Setup
76```bash
77# Initialize directory structure
78mkdir -p {modules,environments/{dev,staging,prod}}
79
80# Set up remote backend (bootstrap S3 + DynamoDB first)
81# Configure backend.tf with encryption and locking
82```
83
84### 2. Module Development
85```bash
86# Create module with standard structure
87cd modules/my-module
88touch main.tf variables.tf outputs.tf versions.tf README.md
89
90# Add validation to variables
91# Use complex types for structured inputs
92# Document outputs with descriptions
93```
94
95### 3. Security Hardening
96```bash
97# Mark sensitive variables
98# Use secret management for credentials
99# Configure state encryption
100# Set up security scanning in CI/CD
101```
102
103### 4. Testing Pipeline
104```bash
105# Install pre-commit hooks
106pre-commit install
107
108# Run validation locally
109terraform init
110terraform validate
111terraform fmt -check
112
113# Security scanning
114tfsec .
115checkov -d .
116
117# Automated tests (critical modules)
118cd tests && go test -v
119```
120
121### 5. Deployment Process
122```bash
123# Plan with output file
124terraform plan -out=tfplan
125
126# Review plan thoroughly
127terraform show tfplan
128
129# Apply only after approval
130terraform apply tfplan
131
132# Verify deployment
133terraform output
134```
135
136### 6. Multi-Environment Management
137```bash
138# Use directory-based isolation for production
139cd environments/prod
140terraform init
141terraform workspace list
142
143# Or use Terragrunt for DRY backend config
144terragrunt plan
145```
146
147## Common Mistakes
148
149❌ **Hardcoding secrets in code** → Use secret management services
150❌ **No state locking** → Enable DynamoDB locking to prevent conflicts
151❌ **Skipping plan review** → Always save and review execution plans
152❌ **No version constraints** → Pin provider and module versions
153❌ **Local state in teams** → Use remote backends for collaboration
154❌ **No security scanning** → Integrate tfsec/Checkov in CI/CD
155❌ **Missing resource tags** → Tag all resources for cost/ownership tracking
156❌ **No automated testing** → Write Terratest for critical modules
157❌ **Monolithic modules** → Break into composable child modules
158❌ **No backup strategy** → Enable S3 versioning on state buckets
159
160## Resources
161
162- **Official Docs**: https://developer.hashicorp.com/terraform/docs
163- **Style Guide**: https://developer.hashicorp.com/terraform/language/syntax/style
164- **Module Registry**: https://registry.terraform.io/
165- **Terragrunt**: https://terragrunt.gruntwork.io/
166- **Terratest**: https://terratest.gruntwork.io/
167- **tfsec**: https://aquasecurity.github.io/tfsec/
168- **Checkov**: https://www.checkov.io/
169- **Best Practices**: https://www.terraform-best-practices.com/
170- **AWS Provider**: https://registry.terraform.io/providers/hashicorp/aws/latest/docs