Hello People, In this blog we will deep dive into the Terraform Project Structure Best practices.
Have you wondered that while we are running commands like terraform plan or apply we are not giving any parameters additional to that terraform commands, how does terraform know which file it should execute.
The answer is simple, whenever you run terraform commands like plan or apply, terraform executes that on all the files having .tf extensions. It doesn't matter to terraform if you have a single file with 1000 lines or 100 .tf files with 10 lines. Terraform is that smart. But we humans are not that smart just joking, we are smart too but in use cases like debugging or modifying any specific resource, do u think it is feasible to go through a file of some thousands of lines.
So For this purpose, we will be using project structure in terraform where we will divide the code into multiple .tf files based on their usecases or creation.
Terraform File Loading
Terraform loads all .tf files in the current directory
Files are loaded in lexicographical order (alphabetical)
File names don't affect functionality, only organization
All .tf files are merged into a single configuration
Recommended File Structure:
project-root/
├── backend.tf # Backend configuration
├── provider.tf # Provider configurations
├── variables.tf # Input variable definitions
├── locals.tf # Local value definitions
├── main.tf # Main resource definitions
├── vpc.tf # VPC-related resources
├── security.tf # Security groups, NACLs
├── compute.tf # EC2, Auto Scaling, etc.
├── storage.tf # S3, EBS, EFS resources
├── database.tf # RDS, DynamoDB resources
├── outputs.tf # Output definitions
├── terraform.tfvars # Variable values
└── README.md # Documentation
File Organization Principles
Separation of Concerns: Group related resources together
Logical Grouping: Organize by service or function
Consistent Naming: Use clear, descriptive file names
Modular Approach: Keep files focused on specific areas
Documentation: Include README and comments
In the above image you can see how we have defined the project structure in Terraform, where we have divided our terraform configuration into multiple files with their usecases.
- main.tf which contains all the resource definitions. This can be further divided on the basis of resources like ec2.tf, s3.tf, vpc.tf, iam.tf, role.tf.... and so on.
- Variables.tf: It will contain all the input variables, so if anyone want to see what all the variables we are passing to this terraform code, he can have a look at this and can have a clear info.
- output.tf: Defines what information to display after running terraform apply or if u want to pass any resource information or data to another resource while creating.
- versions.tf: Locks terraform and pproviders versions for consistency.
- providers.tf: Configure cloud provider settings.
- backend.tf: Configure where Terraform stores statefile.
- terraform.tfvars: Defines the actual varibale values passed for your environment. You cannot push it to GitHub as it may contain sensitive information.
- terraform.tfvars.example: It is like a template showing what variables need values, It can be pushed to Github as it more of a template
- .gitignore: It is a file where you will keep all the files which you do not want to be pushed into the GitHub like the statefile, varibles file. Some of the examples include: .terraform*, *.tfstate, .terraform.lock.hcl, *.tfstate.backup...
Advanced File Organization Patterns
Environment-Specific Structure: We can use separate folders for separate environments like below not including all the files in a single page.
environments/
├── dev/
│ ├── backend.tf
│ ├── terraform.tfvars
│ └── main.tf
├── staging/
│ ├── backend.tf
│ ├── terraform.tfvars
│ └── main.tf
└── production/
├── backend.tf
├── terraform.tfvars
└── main.tf
Best Practices
Consistent Naming:
- Use clear, descriptive file names.
- Follow team conventions
- Use lowercase with hyphens or underscores
Logical Grouping
- Group related resources together
- Separate by AWS service or function
- Consider dependencies when organizing
Size Management
- Keep files manageable (< 200 lines)
- Split large files by functionality
- Use modules for reusable components
Dependencies
- Place provider and backend configs first
- Define variables before using them
- Output values at the end
Documentation
- Include README.md
- Comment complex configurations
- Document variable purposes
Commands for Testing:
terraform validate - To Validate the reorganized structure
terraform fmt -recursive - To format all files consistently across folders
terraform plan - Plan to ensure no changes
terraform apply - Apply if everything looks good
Conclusion:
Terraform's Project Structure is a important thing which many will ignore at first includes all the code in a single file and then later struggle while debugging. So It is better to organize our code separately using file structure which will be helpful for us when we got struck with any errors or dealing with microservices and also easy for anyone to have a quick look and understand what is happening under the hood. See you in the next blog.
Below is the Youtube Video for reference: Tech Tutorials with Piyush — “AWS Terraform Project Structure Best Practices”

Top comments (0)