The Terraform workflow is consistent and predictable. Learning each step deeply will make you faster and help you catch mistakes before they become infrastructure incidents.
Step 1: terraform init
Run terraform init when you first work with a configuration, or when you:
- Add a new provider
- Add a new module
- Change backend configuration
- Clone the repo on a new machine
terraform init # standard init
terraform init -upgrade # upgrade providers to latest allowed version
terraform init -backend-config="bucket=my-bucket" # pass backend config dynamically
terraform init -reconfigure # reconfigure backend (discard old state location)
init creates the .terraform/ directory with downloaded providers and modules. Add .terraform/ and .terraform.lock.hcl (commit this!) to your project. The lockfile pins provider versions for reproducible plans.
Step 2: terraform validate
terraform validate
Checks configuration syntax and internal consistency without accessing remote services. Run this in CI to catch errors early. It does not check if resources exist or if values are valid (that happens at plan time).
Step 3: terraform fmt
terraform fmt # format all .tf files in current directory
terraform fmt -recursive # format subdirectories too
terraform fmt -check # exit code 1 if any file needs formatting (CI check)
Run terraform fmt -check -recursive in CI to enforce consistent formatting.
Step 4: terraform plan
terraform plan # preview changes
terraform plan -out=tfplan # save plan to file
terraform plan -var-file=prod.tfvars # use variable file
terraform plan -target=aws_instance.web # plan only specific resource
terraform plan -destroy # preview what destroy would do
Always read the plan output carefully. Look for:
+green — resource will be created-red — resource will be destroyed~yellow — resource will be updated in-place-/+red/green — resource will be destroyed and recreated (dangerous!)
Step 5: terraform apply
terraform apply # generates plan, prompts "yes" to confirm
terraform apply tfplan # apply a saved plan file (no prompt)
terraform apply -auto-approve # skip confirmation (automation only)
terraform apply -var-file=prod.tfvars
Step 6: terraform destroy
terraform destroy # plan + confirm destruction of all resources
terraform destroy -target=aws_instance.web # destroy specific resource
terraform plan -destroy # preview what would be destroyed
terraform destroy will destroy real infrastructure. Always run terraform plan -destroy first to review the list. Use prevent_destroy = true lifecycle rules on critical resources.
CI/CD Integration Pattern
A standard pattern for Terraform in CI/CD (GitHub Actions, GitLab CI, Atlantis):
| Trigger | Steps |
|---|---|
| Pull Request opened | init → fmt -check → validate → plan → post plan as PR comment |
| PR merged to main | init → apply -auto-approve (with saved plan) |
# Example GitHub Actions step
- name: Terraform Plan
run: |
terraform init
terraform validate
terraform plan -out=tfplan -no-color 2>&1 | tee plan.txt
- name: Terraform Apply
if: github.ref == 'refs/heads/main'
run: terraform apply -auto-approve tfplan
Targeted Operations
# Apply only a specific resource (use sparingly — can leave state inconsistent)
terraform apply -target=module.vpc
terraform apply -target=aws_instance.web
# Refresh state without making changes
terraform apply -refresh-only
Next: Terraform best practices — how to structure projects, manage secrets, write maintainable code, and avoid common pitfalls.