Terraform Associate
Deep Dive
Terraform's core workflow consists of three phases you need to understand in depth for the exam: what happens internally in each one, what files are generated, and how to manage the working directory.
Contents
✏️
1. Write
You write .tf files in HCL describing the desired state of the infrastructure.
🔍
2. Plan
Terraform compares the desired state (code) with the current state (tfstate) and calculates the differences.
🚀
3. Apply
Executes the necessary cloud API calls and updates the state file with the results.
During the write phase, you only edit text files. Terraform does not communicate with any cloud API during this phase. What matters is that the code is syntactically valid (checked by terraform validate) and well formatted (terraform fmt).
# main.tf — describes the DESIRED state
resource "aws_s3_bucket" "data" {
bucket = "mi-empresa-datos-prod"
}
resource "aws_s3_bucket_versioning" "data" {
bucket = aws_s3_bucket.data.id # reference creates an implicit dependency
versioning_configuration {
status = "Enabled"
}
}💡 Before the first init
After writing the configuration, you must run terraform init to download the providers and modules. Without init, plan and apply will fail because the plugins don't exist.
terraform plan is the most important phase for the exam. Internally it performs several steps:
Loads the configuration
Reads every .tf file in the working directory and parses it.
Loads the current state
Reads terraform.tfstate (local or remote) to learn the last known real state.
Refreshes the state
Queries the cloud APIs to verify that the state in tfstate still matches reality (can detect drift).
Builds the graph
Generates a DAG (directed acyclic graph) with the dependencies between resources.
Calculates the diff
Compares the desired configuration vs the current state and determines: + create, - destroy, ~ modify, -/+ replace.
Shows the plan
Prints the changes on screen and/or saves the binary plan (-out=plan.out).
| Symbol | Meaning | Example |
|---|---|---|
| + | Create a new resource | aws_vpc.main will be created |
| - | Destroy an existing resource | aws_vpc.old will be destroyed |
| ~ | Modify a resource in-place | aws_instance.web will be updated in-place |
| -/+ | Destroy and recreate (replace) | aws_instance.web must be replaced |
| <= | Read a data source | data.aws_ami.ubuntu will be read |
Apply executes the API calls defined in the plan. If a plan file is passed (terraform apply plan.out), Terraform uses exactly that plan without recalculating. If none is passed, it generates a new plan and asks for confirmation.
# Recommended flow in production: terraform plan -out=tfplan # saves the exact plan terraform apply tfplan # applies exactly that plan (no manual confirmation) # Quick flow (development): terraform apply # generates a plan + asks for "yes" terraform apply -auto-approve # generates a plan + applies without asking
⚠️ Apply modifies real infrastructure
Use -auto-approve only in CI/CD pipelines where you already reviewed the plan in a previous step. Never in production from your own machine without reviewing the plan first.
After terraform init, the .terraform/ directory is created with everything needed to run plan and apply.
.terraform/providers/
Provider binaries downloaded from the registry. Heavy, not committed to VCS.
.terraform/modules/
Modules downloaded from remote sources (registry, GitHub, S3…).
.terraform/terraform.tfstate
Backend state (only if you use a remote backend). Not the main tfstate.
terraform.tfstate
The main state (local backend). Contains the real state of the managed infra.
terraform.tfstate.backup
Automatic backup of the tfstate prior to each apply.
.terraform.lock.hcl
Lock file for provider versions. Committed to VCS.
The .terraform.lock.hcl file pins the exact versions of the installed providers so that every team member uses exactly the same versions.
# .terraform.lock.hcl (generated by terraform init)
provider "registry.terraform.io/hashicorp/aws" {
version = "5.31.0"
constraints = "~> 5.0"
hashes = [
"h1:ABC123...", # binary hash for integrity verification
"zh:XYZ789...",
]
}| File / Directory | Commit? | Reason |
|---|---|---|
| *.tf | ✅ Yes | It is the source code of the infrastructure |
| .terraform.lock.hcl | ✅ Yes | Pins exact provider versions for reproducibility |
| terraform.tfstate | ❌ No | Sensitive data in plain text; use a remote backend |
| terraform.tfstate.backup | ❌ No | Same reason as tfstate |
| .terraform/ | ❌ No | Heavy binaries, regenerable with terraform init |
| *.tfvars with secrets | ❌ No | Credentials, tokens, passwords |
| *.auto.tfvars without secrets | ✅ Yes | Non-sensitive environment variables (region, sizes, etc.) |
Did you get this topic?
Test what you just learned
A developer runs terraform plan and sees a resource aws_instance marked with -/+. What does this mean and what will happen in the next apply?
Put what you learned to the test with original Terraform Associate exam questions.
Start Terraform Associate mock examUnlimited mock exams with the Pro plan
Log in to track your progress.