How Terraform Really Works Under the Hood (Modules, State, DAGs Explained)
Learn how Terraform actually works behind the scenes, including DAG-based execution, state files, root modules, and project structure. A technical deep dive for DevOps engineers.

How Terraform Really Works Under the Hood (Modules, State, DAGs Explained)
First time using Terraform? Start here: Beginner’s Guide to Terraform, it lays the groundwork for everything that follows.
Introduction
You’ve probably used Terraform to spin up an EC2 instance or an S3 bucket and thought: “Wow, that was easy.” But what’s actually going on behind the scenes when you run terraform apply
? How does Terraform know what order to create things in? What’s in that mysterious .terraform/
folder?
This post is for DevOps engineers, SREs, and infrastructure-minded developers who want to understand how Terraform really works under the hood, from state management and dependency graphs to the module system and directory structure. Knowing this stuff is the difference between “getting it to work” and building scalable, team-ready infrastructure.
Let’s crack open the black box.
1. Terraform’s Execution Flow at a Glance
Here’s what Terraform does, step-by-step:
terraform init → terraform validate → terraform plan → terraform apply → terraform destroy
What happens at each stage:
init
: Downloads the provider plugins and sets up.terraform/
validate
: Checks that your configuration is syntactically validplan
: Compares your configuration to the existing state to show what will changeapply
: Provisions (or updates/destroys) infrastructure based on the plandestroy
: Deletes all resources defined in your code
Pro Tip:
terraform plan -out=tfplan
lets you save a plan to disk and apply it later withterraform apply tfplan
for more auditable workflows.
2. The .terraform
Directory: What’s Inside?
Once you run terraform init
, Terraform creates a hidden .terraform/
folder in your project root.
Here’s what it typically contains:
.terraform/
├── providers/ → Downloaded binaries for each provider (e.g., AWS)
├── terraform.lock.hcl → Dependency lock file
├── plugins/ → Deprecated in newer versions
└── modules/ → Caches reused modules
Why it matters:
- Caching: Avoids re-downloading provider binaries each time
- Locking: Ensures consistent provider versions across machines
- Modular reusability: Improves performance by caching modules
Never manually edit anything in
.terraform/
. You can delete it safely and re-init the project.
3. State Files: Terraform’s Source of Truth
Terraform stores a snapshot of your infrastructure in a state file called terraform.tfstate
. This file is critical.
Why does it exist?
Terraform is declarative, it knows what you want, but it needs to compare that to what you already have.
Without state, Terraform can’t:
- Track what resources exist
- Detect drift
- Create efficient plans
- Manage dependencies
Local vs Remote State:
Type | Pros | Cons |
---|---|---|
Local (terraform.tfstate ) |
Simple for small projects | Not collaborative, risky in teams |
Remote (e.g., S3 + DynamoDB) | Team-safe, state locking, backups | Slightly more setup |
Never manually edit the
.tfstate
file. Useterraform state
commands to inspect or modify state safely.
4. The DAG: Terraform’s Dependency Brain
Terraform builds a Directed Acyclic Graph (DAG) of resources. This graph determines the order of operations during a plan
or apply
.
Example:
resource "aws_vpc" "main" {
...
}
resource "aws_subnet" "web" {
vpc_id = aws_vpc.main.id
...
}
Terraform sees that aws_subnet.web
depends on aws_vpc.main
, and will always create the VPC first. If a resource fails, dependent resources are skipped.
DAG Benefits:
- Parallelism: Terraform can build independent resources concurrently
- Safety: Ensures correct dependency ordering
- Clarity: You can visualize the graph with
terraform graph | dot -Tpng > graph.png
Understanding Terraform’s DAG helps debug strange errors when a resource doesn’t seem to behave as expected.
5. The Root Module and Implicit Structure
A Terraform module is just a folder containing .tf
files. When you run Terraform in a directory, that directory is the root module.
All .tf
files in the directory are loaded and combined. There’s no special priority based on filenames like main.tf
, it’s just convention.
Root Module Example:
infra/
├── main.tf
├── variables.tf
├── outputs.tf
└── terraform.tfvars
Each of these files contributes to one big module that Terraform uses as the root.
You can nest modules using the
module
block to reuse code and organize your infra.
module "network" {
source = "./modules/network"
cidr_block = var.vpc_cidr
}
6. File Loading Order and Variable Precedence
Terraform loads all .tf
files in lexical order, but treats them as a single config. There’s no need to import
or include
anything manually.
Variable precedence:
- CLI flags (
-var
) or-var-file
terraform.tfvars
- Environment variables
- Default values in
variables.tf
Use
terraform console
to test variable evaluation and expressions interactively.
7. Best Practices: Structure, Versioning, and Secrets
Following clean practices helps avoid headaches and keeps infra predictable.
Recommended Project Layout
project-root/
├── modules/
│ └── vpc/
│ └── main.tf
├── main.tf
├── variables.tf
├── outputs.tf
├── terraform.tfvars
└── .terraform/ (generated)
Additional Best Practices:
- Use
terraform fmt
andvalidate
in CI/CD - Lock provider versions with
required_providers
- Use remote state for team environments
- Store secrets in environment variables or Vault, not in
.tf
files
Consider using tools like
sops
,chamber
, or Terraform Cloud’s variable store for secrets management.
8. Visual Guide: Anatomy of a Terraform Project Folder
project-name/
├── .terraform/ # auto-generated
├── terraform.tfstate # local state
├── terraform.tfstate.backup
├── main.tf
├── variables.tf
├── outputs.tf
├── terraform.tfvars # input variable values
├── modules/
│ └── my-module/
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
└── README.md
Conclusion
Terraform may look simple, but behind the scenes it’s a sophisticated system that uses declarative code, DAGs, state management, and a modular architecture to manage infrastructure at scale.
Understanding how Terraform really works helps you:
- Avoid silent failures or drift
- Optimize performance via parallelism
- Structure projects for team collaboration
- Debug like a pro
Thanks for reading!
More Articles
- What Is Terraform and How to Use It (2025 Guide)
- Manual vs Terraform: What’s the Best AWS Workflow for Data Engineers?
Frequently Asked Questions
- Q: Can I delete the .terraform/ folder?
- A: Yes. It’s safe to delete. Terraform will regenerate it when you run terraform init again.
- Q: Why does Terraform need a state file?
- A: The state file tracks your infrastructure, enabling Terraform to know what to create, update, or delete.
- Q: How does Terraform know what order to create resources in?
- A: Terraform builds a dependency graph (DAG) based on resource relationships and executes resources in that order.
- Q: Is main.tf a special file?
- A: No. All .tf files in the root module are treated equally. main.tf is just a naming convention for readability.
- Q: Can I use multiple state files?
- A: Yes. You can manage multiple states by splitting infrastructure into different root modules or using workspaces.
Want to keep learning?
Explore more tutorials, tools, and beginner guides across categories designed to help you grow your skills in real-world tech.
Browse All Categories →