100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
HCL

File and Directory Structure Conventions

Consistent file layout and naming conventions keep Terraform projects navigable as they grow, separating variables, outputs, providers, and resources predictably.

Organizing Terraform CodeBeginner7 min readJul 9, 2026
Analogies

File and Directory Structure Conventions

Terraform does not enforce any particular file layout — it loads every .tf file in a directory and merges them into a single configuration regardless of filename. That flexibility means teams must impose their own conventions, and the community has converged on a fairly consistent baseline: main.tf for primary resource definitions, variables.tf for input declarations, outputs.tf for exported values, providers.tf (or versions.tf) for provider and required_version blocks, and terraform.tfvars for default variable assignments. This predictable skeleton lets any engineer open an unfamiliar repository and immediately know where to look for a given concern.

🏏

Cricket analogy: Terraform not enforcing file layout is like the laws of cricket not mandating a specific practice schedule, yet every serious academy converges on the same routine — nets, fitness, video review — so any new coach recognizes the structure immediately.

Root Modules vs. Reusable Modules

A typical repository separates a top-level root configuration (the environment-specific entry point that calls modules and holds backend configuration) from a modules/ directory containing reusable, environment-agnostic building blocks such as modules/vpc or modules/eks-cluster. The root module should stay thin — mostly module calls and variable wiring — while the heavy resource logic lives inside the reusable modules, making it possible to version and test modules independently of any single environment.

🏏

Cricket analogy: The root module staying thin while modules/ holds the heavy logic is like a captain's thin game plan calling on reusable, well-drilled units — the pace attack, the top order — each independently trained regardless of which match it's deployed in.

Multi-Environment Layouts

For projects managing multiple environments as separate root configurations rather than workspaces, a common pattern is an environments/ directory with one subdirectory per environment (environments/dev, environments/staging, environments/prod), each containing its own backend.tf, terraform.tfvars, and a short main.tf that references shared modules by relative or registry path. This keeps state, credentials, and variable values cleanly partitioned per environment while maximizing code reuse through the shared modules directory.

🏏

Cricket analogy: An environments/ directory with dev, staging, and prod subfolders is like separate training venues for the A-team, the reserves, and the senior squad, each with its own kit and schedule but drawing on the same shared coaching modules.

bash
repo/
 modules/
    vpc/
       main.tf
       variables.tf
       outputs.tf
    eks-cluster/
        main.tf
        variables.tf
        outputs.tf
 environments/
     dev/
        main.tf
        backend.tf
        terraform.tfvars
     prod/
         main.tf
         backend.tf
         terraform.tfvars

Terraform reads file contents alphabetically-agnostic and merges everything, so main.tf is a human convention, not a technical requirement — you could name every file zzz.tf and it would behave identically. Naming conventions exist purely for the humans who will read the repository later.

Avoid deeply nested or inconsistent module trees where the same logical resource (e.g. a VPC) is defined slightly differently in three different directories. Drift between near-duplicate modules is one of the most common causes of configuration sprawl and unexplained environment differences.

  • Terraform loads all .tf files in a directory regardless of name; file naming conventions are a human, not technical, requirement.
  • Common baseline files: main.tf, variables.tf, outputs.tf, providers.tf/versions.tf, terraform.tfvars.
  • Separate reusable modules/ from environment-specific root configurations for cleaner reuse and testing.
  • An environments/ directory with one subfolder per environment keeps state and credentials cleanly partitioned.
  • Keep root modules thin — mostly module calls and variable wiring — pushing detailed resource logic into modules.
  • Consistent structure reduces onboarding time and prevents configuration drift between near-duplicate resource definitions.

Practice what you learned

Was this page helpful?

Topics covered

#HCL#TerraformInfrastructureAsCodeStudyNotes#DevOps#FileAndDirectoryStructureConventions#File#Directory#Structure#Conventions#StudyNotes#SkillVeris