
π What Is a Terraform Project Structure?
Terraform project structure defines how you organize files, modules, environments, and state so that:
- Infra is scalable
- Teams can collaborate safely
- Changes donβt break production
- CI/CD can manage it cleanly
π§± Core Principles (Interview Gold)
When explaining structure, always anchor to these:
- Separation of concerns
- Reusability via modules
- Environment isolation
- Remote state & locking
- Least privilege
- CI/CD friendly
ποΈ Recommended Production AWS Terraform Structure
β Standard & Scalable Layout
terraform-aws/
βββ modules/
β βββ vpc/
β β βββ main.tf
β β βββ variables.tf
β β βββ outputs.tf
β βββ ec2/
β βββ rds/
β βββ alb/
β
βββ envs/
β βββ dev/
β β βββ main.tf
β β βββ terraform.tfvars
β β βββ backend.tf
β βββ staging/
β βββ prod/
β
βββ provider.tf
βββ versions.tf
βββ README.md
π§© Why This Structure Works
| Folder | Purpose |
|---|---|
modules/ | Reusable infra components |
envs/ | Environment-specific configuration |
backend.tf | Remote state per env |
terraform.tfvars | Env-specific values |
πΉ modules/ (MOST IMPORTANT)
Rule: One module = One responsibility
Example: modules/vpc
# modules/vpc/main.tf
resource "aws_vpc" "this" {
cidr_block = var.cidr
}# modules/vpc/variables.tf
variable "cidr" {
type = string
}# modules/vpc/outputs.tf
output "vpc_id" {
value = aws_vpc.this.id
}π Modules must never:
- Contain backend config
- Hardcode values
- Reference environments directly
πΉ envs/ (Environment Isolation)
Each environment has its own state file.
Example: envs/dev/main.tf
module "vpc" {
source = "../../modules/vpc"
cidr = var.vpc_cidr
}terraform.tfvars
vpc_cidr = "10.0.0.0/16"backend.tf
terraform {
backend "s3" {
bucket = "my-tf-state-dev"
key = "vpc/terraform.tfstate"
region = "ap-south-1"
dynamodb_table = "tf-lock"
}
}π Remote State Best Practices (AWS)
Use:
- S3 β state storage
- DynamoDB β state locking
Why?
- Prevents concurrent
apply - Enables team collaboratio
- Disaster recovery
π§ Interview Tip:
βEach environment has an isolated state backend to avoid cross-environment impact.β
π versions.tf (Pin Everything)
terraform {
required_version = ">= 1.5.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}π Prevents breaking upgrades.
πΉ provider.tf
provider "aws" {
region = var.region
}Use variables for:
- Region
- Account (via profiles or assume role)
π Security Best Practices
β NEVER:
- Commit
.tfstate - Commit secrets in
.tfvars
β ALWAYS:
*.tfstate
*.tfstate.backup
.terraform/
Use:
- AWS Secrets Manager
- SSM Parameter Store
- Vault
π CI/CD Friendly Structure
Pipeline example:
cd envs/dev
terraform init
terraform plan
terraform applyProd:
- Manual approval
- Read-only plan
- Restricted IAM role
π§ͺ Small vs Large Team Structures
Small Team
terraform/
βββ main.tf
βββ variables.tf
βββ outputs.tf
Enterprise (Recommended)
terraform/
βββ modules/
βββ envs/
βββ policies/
βββ pipelines/
π« Common Bad Practices (Say This in Interviews)
- One state file for all envs β
- Hardcoded AWS credentials β
- No module abstraction β
- No state locking β
- Applying from local laptops in prod β
π§Ύ Interview-Ready Summary (MEMORIZE)
βIn AWS Terraform projects, we use a module-based structure with environment isolation. Each environment has its own backend and tfvars, remote state stored in S3 with DynamoDB locking, provider and version pinning, and CI/CD-controlled applies.β
π₯ This answer signals real production experience.