Terraform Best Practices for Production — Modules, State Management & CI/CD
Learn the Terraform patterns that separate amateur scripts from production-grade Infrastructure as Code: module design, remote state, Terragrunt, and CI/CD pipeline integration.
Rajesh Vardhan Busam
Cloud Engineer & IaC Specialist
Writing Terraform that works on your laptop is easy. Writing Terraform that a team of engineers can collaborate on safely — across multiple environments and AWS accounts — is a different challenge entirely. These are the patterns that make the difference.
1. Use Remote State (Always)
Never store Terraform state locally in production. Use an S3 backend with DynamoDB locking:
terraform {
backend "s3" {
bucket = "my-company-tfstate"
key = "prod/vpc/terraform.tfstate"
region = "ap-south-1"
dynamodb_table = "terraform-locks"
encrypt = true
}
}
The DynamoDB table prevents two engineers from running terraform apply simultaneously, which would corrupt the state file.
2. Structure with Modules
Don't write monolithic Terraform. Break infrastructure into reusable modules:
modules/
vpc/ → creates VPC, subnets, route tables
eks/ → creates EKS cluster, node groups
rds/ → creates RDS instance, parameter groups
environments/
dev/ → calls modules with dev-specific variables
staging/
prod/
Each environment just calls the same modules with different variable values — no code duplication.
3. Pin Provider and Module Versions
Always pin your provider versions. An unpinned hashicorp/aws provider can introduce breaking changes on terraform init:
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.40"
}
}
4. Use Terragrunt for Multi-Environment DRY
If you have three environments and five modules, that's 15 backend configurations. Terragrunt eliminates this duplication with a root terragrunt.hcl that generates backend config dynamically for every module.
5. Run Terraform in CI/CD, Not Locally
Production Terraform runs should happen in CI/CD (GitHub Actions, GitLab CI, or Atlantis), never from a developer's laptop. This ensures:
- Consistent environment (same Terraform version)
- Audit trail (who applied what, when)
- Pull request workflow (plan output in PR comment, apply on merge)
6. Validate and Scan Before Apply
Add these steps to your Terraform CI pipeline:
terraform fmt -check— enforce consistent formattingterraform validate— catch syntax errorscheckov -d .— scan for security misconfigurationsterraform plan— review changes before applying
7. Use Workspaces Only for Ephemeral Environments
Terraform workspaces are useful for feature branch environments (spin up, test, destroy). Do not use workspaces for long-lived environments like dev/staging/prod — use separate state files per environment instead.
Our Infrastructure as Code course covers all of these patterns with hands-on AWS labs — building a complete multi-environment Terraform setup with Terragrunt and a full CI/CD pipeline.
Tags
