4 Terraform beginner questions with detailed answers, HCL examples, and interview tips.
Quick Answer
tfenv is a Terraform version manager that lets you install, switch, and pin specific Terraform versions per project using a .terraform-version file. Version pinning prevents breaking changes when a new Terraform release changes provider behavior or HCL syntax.
Detailed Answer
Think of a chef who needs different ovens for different recipes — one recipe requires a convection oven at 350F, another requires a gas oven at 400F. tfenv lets you switch ovens (Terraform versions) per recipe (project) without uninstalling and reinstalling each time.
tfenv works like nvm for Node.js or pyenv for Python. You install it once, then use tfenv install to download specific Terraform versions. tfenv use 1.7.5 switches your active version. Most importantly, you can place a .terraform-version file in your project root containing just the version number (e.g., 1.7.5), and tfenv automatically switches to that version when you enter the directory.
Version pinning matters because Terraform versions are not always backward-compatible. A state file written by Terraform 1.8 cannot be read by Terraform 1.7. Provider behavior can change between versions — for example, the AWS provider might change default values for security group rules. If one team member runs Terraform 1.8 and another runs 1.7, they can corrupt the state file or produce different plan outputs from the same code.
At production scale, teams enforce version pinning at multiple levels: .terraform-version in the repo root for tfenv users, required_version constraint in the Terraform block (e.g., required_version = "~> 1.7.0"), and a pinned Terraform version in the CI/CD pipeline Docker image. This triple-lock ensures everyone — developers, CI, and production — uses the exact same Terraform version.
The non-obvious gotcha is that tfenv install latest installs the newest version, which might be a major release with breaking changes. Always use explicit version numbers in .terraform-version files, never latest. Also, some teams forget to update the required_version constraint when they upgrade, causing confusion when tfenv installs a newer version that the constraint blocks.
Code Example
# Install tfenv (macOS)
brew install tfenv
# List available Terraform versions
tfenv list-remote | head -10
# Install a specific version
tfenv install 1.7.5
# Switch to that version
tfenv use 1.7.5
# Verify active version
terraform version # Terraform v1.7.5
# Pin version per project (create .terraform-version file)
echo '1.7.5' > .terraform-version
# Now entering this directory auto-switches to 1.7.5
cd /projects/payments-infra && terraform version # v1.7.5
cd /projects/legacy-infra && terraform version # v1.5.7 (from its own .terraform-version)
# Also pin in Terraform code
terraform {
required_version = "~> 1.7.0" # Allows 1.7.x but not 1.8.0
}Interview Tip
A junior engineer typically says they install Terraform from the website, but for a senior role, the interviewer is actually looking for version management discipline. Explain the .terraform-version file for automatic switching, the required_version constraint in HCL as a safety net, and the CI pipeline pinning as the third lock. Mentioning state file incompatibility between versions and provider behavior changes as the reasons why pinning matters shows you have dealt with real multi-team Terraform environments.
◈ Architecture Diagram
┌─────────────────────────────┐ │ Project A (.terraform-ver) │ │ → 1.7.5 │ ├─────────────────────────────┤ │ Project B (.terraform-ver) │ │ → 1.5.7 │ ├─────────────────────────────┤ │ CI Pipeline (Docker image) │ │ → 1.7.5 (pinned) │ └─────────────────────────────┘
💬 Comments
Quick Answer
Infrastructure as Code means defining servers, networks, and cloud resources in version-controlled configuration files instead of clicking through a console or running one-off scripts, so infrastructure changes can be reviewed, tested, and reproduced exactly. Terraform's declarative model means you describe the end state you want, and Terraform figures out the exact steps to get there — including safely modifying or destroying existing resources — rather than you writing and maintaining those steps yourself.
Detailed Answer
Think of IaC like the difference between giving someone a furnished blueprint versus a list of instructions like 'walk to the store, buy a couch, carry it up two flights of stairs, put it in the corner.' The instruction list breaks the moment anything changes — the store is closed, the stairs are blocked — because it describes actions, not the outcome. A blueprint just says 'a couch belongs in this corner,' and whoever executes it figures out how to make that true right now, whatever the current situation is. Imperative provisioning scripts are the instruction list; Terraform's declarative configuration is the blueprint.
Infrastructure as Code exists because manually clicking through a cloud console to create resources is unrepeatable and unreviewable — nobody can diff two consoles, and reproducing a production environment for staging means re-clicking through dozens of screens and hoping you remembered every setting. Terraform specifically chose a declarative model, as opposed to imperative tools like a bash script running aws ec2 run-instances, because declarative code stays correct even as the real world changes: if someone manually deletes a resource Terraform created, your configuration file doesn't need to change at all — Terraform detects the drift on the next plan and knows how to fix it.
Internally, Terraform maintains a state file that records what resources it created and their exact current attributes. When you run terraform plan, it queries your cloud provider's API for the real current state of each resource, compares that against both your desired configuration and its recorded state file, and computes a diff — additions, changes, and deletions — without touching anything. Only terraform apply actually executes that diff, calling the cloud provider's API to create, modify, or destroy resources in dependency order (Terraform builds a dependency graph from resource references, so a subnet is always created before the EC2 instance that needs it).
In production, this state file becomes the single source of truth for what Terraform believes exists, which is why teams store it remotely (in S3 with DynamoDB locking, or Terraform Cloud) rather than on a laptop — two engineers running apply against the same infrastructure with different local state files is one of the most common ways teams accidentally destroy production resources. Terraform plans are also what make infrastructure changes reviewable in a pull request: reviewers read the plan's output (2 to add, 1 to change, 0 to destroy) the same way they'd read a code diff, before anything is actually applied.
The gotcha most engineers hit early: because Terraform is declarative, deleting a resource block from your configuration doesn't just stop managing it — it tells Terraform that resource should no longer exist, and the next apply will destroy it. Engineers coming from imperative scripting instinctively expect 'removing code' to be a no-op, but in Terraform, removing a resource block is an explicit instruction to tear that resource down.
Code Example
# main.tf — declarative: describes desired end state, not steps to get there
resource "aws_instance" "payments_api" {
ami = "ami-0c55b159cbfafe1f0" # base image for the instance
instance_type = "t3.medium"
subnet_id = aws_subnet.private.id # Terraform infers: create subnet first
tags = {
Name = "payments-api"
}
}
resource "aws_subnet" "private" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.1.0/24"
}
# Preview the diff before touching anything — reviewable like a code diff
terraform plan -out=tfplan
# Output: Plan: 2 to add, 0 to change, 0 to destroy.
# Only this step actually calls the AWS API
terraform apply tfplan
# State lives remotely so two engineers never diverge
terraform {
backend "s3" {
bucket = "acme-terraform-state"
key = "payments-api/prod.tfstate"
dynamodb_table = "terraform-locks" # prevents concurrent apply from two laptops
}
}Interview Tip
A junior engineer typically defines IaC as 'writing infrastructure in code files' without explaining declarative versus imperative or the role of state. For a senior or architect role, the interviewer is actually looking for you to explain why the state file matters operationally — remote state with locking to prevent concurrent applies, drift detection on the next plan, and the specific gotcha that removing a resource block is a destroy instruction, not a no-op. Being able to describe how Terraform builds a dependency graph from resource references, rather than requiring you to manually order creation steps, shows you understand what 'declarative' actually buys you over a shell script.
◈ Architecture Diagram
Imperative script: Declarative (Terraform):
1. Create VPC ┌─────────────────────┐
2. Create subnet │ desired state (.tf) │
3. Create instance └──────────┬───────────┘
4. If step 2 fails, what now? │ plan/apply
(you write the recovery logic) ▼
┌─────────────────────┐
│ Terraform figures │
│ out create order + │
│ reconciles drift │
└─────────────────────┘💬 Comments
Quick Answer
State maps your configuration to real resources; Terraform uses it to plan changes and detect drift.
Detailed Answer
terraform.tfstate records resource IDs and metadata so Terraform knows what it manages. Without it, Terraform can't map config to reality. It can contain secrets, so store it in an encrypted remote backend, never in Git. Losing state means Terraform no longer knows about your infrastructure.
Interview Tip
Stress: remote, encrypted, locked — never in Git.
💬 Comments
Quick Answer
plan computes and shows the change set without modifying anything; apply executes it. Reviewing the plan prevents surprises.
Detailed Answer
plan diffs desired config against state and shows creates/updates/destroys. Reviewing it (ideally in a PR) catches accidental destroys before they happen. apply then makes those exact changes. In CI, save the plan (-out) and apply that saved plan so what you reviewed is what runs.
Interview Tip
Mention -out to apply the exact reviewed plan.
💬 Comments