IaC Certification

HashiCorp Terraform Associate (003) Prep Kit: Objectives, Practice Questions & Cheat Sheet

The HashiCorp Certified: Terraform Associate is the one certification almost every infrastructure, platform, and DevOps role now lists, and it is unusual among cloud-era exams in two ways. First, it is genuinely useful: the objectives map almost one-to-one onto the things you do on a real Terraform team, so studying for it makes you better at the job rather than just better at the exam. Second, it is failable by competent people — not because it is hard, but because it probes the exact handful of distinctions that working engineers gloss over: when count breaks and for_each does not, what terraform init actually downloads, why terraform plan -refresh-only exists, what the difference is between terraform state rm and terraform destroy. People who have shipped Terraform for two years walk in confident and lose four or five marks on those distinctions.

This lesson is the prep kit for the 003 objective set (the version current in 2026, valid for both Terraform 1.x and OpenTofu, which the exam treats as interchangeable for the concepts it tests). It is not a re-teach of Terraform from scratch — the rest of this course does that, and the fundamentals lesson is the place to start if any concept here is unfamiliar. It is the layer on top: the objective-by-objective checklist with weightings so you know where the marks are, a bank of practice questions written in the style the real exam uses (with the reasoning for every right answer and why the tempting wrong ones are wrong), a focused tour of the topics candidates most reliably confuse, a one-page cheat sheet to revise the night before, and the exam logistics so nothing on the day surprises you. The goal is simple: pass on the first attempt, and understand why each answer is right so the knowledge survives the exam.

Learning objectives

By the end of this lesson you will be able to:

Prerequisites

This is the capstone of the KloudVin Terraform Zero-to-Hero course, so the assumption is that you have worked through (or already know) the material in the earlier lessons: HCL and the core workflow, modules, state at scale, and troubleshooting. If you have run init/plan/apply/destroy for real, written at least one module with typed variables and outputs, and configured a remote backend once, you are ready. If any of those are shaky, study that lesson first — the exam rewards hands-on muscle memory more than memorisation, and a fortnight of building beats a month of flashcards. HashiCorp recommends roughly six months of hands-on Terraform before sitting the exam, but motivated engineers with a real project pass comfortably sooner.

How the exam is built: the objective domains and their weight

The 003 blueprint is published by HashiCorp as nine objective domains. The exam does not publish a per-domain percentage the way AWS does, but the relative emphasis is well established from the objective wording and the experience of thousands of candidates. The table below gives each domain, what it actually covers, and a realistic weight band so you can prioritise. Treat the bands as “where the marks cluster”, not gospel percentages.

# Objective domain What it covers Weight band
1 Understand IaC concepts Declarative vs imperative; what IaC buys you (versioning, repeatability, self-service); idempotency Low
2 Understand the purpose of Terraform (vs other IaC) Multi-cloud/provider-agnostic; provisioning vs configuration management; the provider ecosystem; benefits of state Low
3 Understand Terraform basics Providers + version constraints; terraform init and what it downloads; plugin/provider installation; provider authentication High
4 Use Terraform outside core workflow import, state subcommands (mv/rm/list/show), taint/-replace, terraform fmt, validate, workspaces (CLI), -refresh-only High
5 Interact with Terraform modules Module sources (registry, Git, local), versions, inputs/outputs, calling modules, the public registry Medium
6 Use the core Terraform workflow write → plan → apply; init, plan, apply, destroy; -target, -var/-var-file; auto-approve; the dependency graph High
7 Implement and maintain state Local vs remote backends; state locking; sensitive data in state; backend block; state migration; terraform_remote_state High
8 Read, generate, and modify configuration Variables (types, validation, sensitive), outputs, locals, data sources, built-in functions, count/for_each/dynamic, resource addressing, dependencies High
9 Understand HCP Terraform / Terraform Cloud capabilities Remote runs, remote state, private registry, Sentinel/policy, workspaces in HCP, VCS-driven runs Medium

The pattern to read off this table: the marks live in the mechanics of doing the work — domains 3, 4, 6, 7, and 8. The conceptual domains (1 and 2) are quick marks you should bank with minimal study. HCP/Terraform Cloud (domain 9) is worth a focused hour even if you only ever use open-source Terraform, because it always appears and is easy to neglect. If your time is short, over-invest in state (7), configuration constructs (8), and the outside-core-workflow commands (4) — that is where prepared candidates separate from unprepared ones.

A useful way to structure revision is by failure mode. The conceptual domains fail from carelessness (reading too fast); the mechanical domains fail from genuine gaps. Spend your last week on the mechanics.

The question formats you will see

Knowing the shapes in advance removes a surprising amount of exam-day friction:

Format How it appears Tactic
Multiple choice One correct answer of four Eliminate two obviously wrong, then decide between the two plausible — that is where the real test is
Multiple response “Select TWO” / “Select THREE” — partial credit is not given The stem tells you how many; if you can only justify one, you are missing something
True / False A single statement to judge Watch absolute words — “always”, “never”, “must” are often the falsifier
Fill in the blank Type the exact command/keyword Spelling and exact subcommand matter (terraform state mv, not move)
Text-match / scenario A short scenario, pick the command or behaviour Map the scenario to the minimal correct action

There are no hands-on labs and no code you must write from a blank screen — it is entirely recognition and recall, which is why a cheat sheet and targeted practice questions are the highest-leverage prep.

Practice question bank (with explained answers and why distractors fail)

These are written in the exam’s idiom and ordered roughly by domain. Read each, commit to an answer before reading the explanation, and pay as much attention to why the wrong answers are wrong as to the right one — that habit is what the exam rewards. Answers and full reasoning follow each block.

Q1 — Core basics (domain 3)

Which command downloads provider plugins and initialises the backend, and must be run before plan or apply in a fresh working directory?

Answer: B. terraform init is the first command in any working directory: it downloads the providers declared in required_providers, installs modules, and initialises the configured backend. A (terraform get) only downloads/updates modules — it does not install providers or initialise the backend, so it is insufficient. C (terraform refresh) is deprecated in favour of plan -refresh-only/apply -refresh-only and reconciles state with reality; it neither installs plugins nor initialises a backend. D (terraform providers) prints the providers a configuration requires — it is a reporting command, not an installer. The trap here is that all four are real commands, so recognition alone is not enough; you have to know what each does.

Q2 — count vs for_each (domain 8, the classic)

You manage five S3 buckets using count over a list. You delete the second element from the list and run apply. What happens?

Answer: C. With count, each instance is addressed by its list index (aws_s3_bucket.this[0], [1], …). Removing the second element shifts every later element down by one index, so Terraform sees [1] now pointing at what used to be [2], [2] at the old [3], and so on — it plans to destroy and recreate everything from the removed position onward, and destroys the now-surplus last index. A is what you wanted and what for_each would have given you, but count cannot do it. B understates the blast radius — it is not one bucket, it is the tail of the list. D is wrong because count is emphatically index-dependent, which is the whole point of the question. The lesson the exam is teaching: use for_each (keyed by a stable string) when elements can be added or removed from the middle of a collection.

Q3 — for_each requirements (domain 8)

Which of the following can you pass to for_each? (Select TWO.)

Answer: B and C. for_each accepts a map or a set of strings — each element must have a unique, known string key that becomes the instance address (resource.name["key"]). A is the trap: a list is not directly accepted; you must convert it with toset(var.list) first (and only if the values are unique). D is simply the wrong type — a number is not a collection. Knowing that for_each needs a map/set, and that the idiomatic way to feed it a list is toset(...), is one of the highest-frequency facts on the exam.

Q4 — state, sensitive data (domain 7)

A teammate says “we don’t need to secure the state backend because we never put passwords in Terraform.” Why are they wrong?

Answer: B. Terraform writes resource attributes into state, and many of those are sensitive even when you never typed a secret yourself — an RDS instance’s initial password, a generated random_password, a connection string, an access key returned by a provider. All of it lands in state in plaintext. That is precisely why the backend must be encrypted and access-controlled. A is false: open-source Terraform does not encrypt local state at rest by default (remote backends like S3/Azure Blob/GCS can be configured to encrypt, but that is the backend’s feature, not Terraform’s). C is false — state holds far more than IDs. D is the subtle trap: sensitive = true only redacts a value from CLI output; it does not remove or encrypt the value in the state file. This four-way distinction is a favourite.

Q5 — taint vs replace (domain 4)

You want to force a single resource to be destroyed and recreated on the next apply, using the current, recommended approach. What do you do?

Answer: B. The current, recommended way to force replacement is the -replace flag on plan/apply, because it shows you the replacement in the plan before you commit to it. A (terraform taint) does the same thing but is deprecated in favour of -replace; the exam tests that you know -replace is the modern equivalent (it may still ask what taint did). C destroys the resource and recreates it on the next apply, but it does so in two steps with a window where the resource does not exist, and -target is a blunt instrument meant for recovery, not routine replacement — not the clean single-operation answer. D is actively dangerous: state rm only makes Terraform forget the resource (it keeps existing in the cloud, now unmanaged), so the next apply creates a duplicate rather than replacing the original. Knowing that taint-replace (one deprecated, one current) and that state rm ≠ replacement is the exam’s intent.

Q6 — local vs remote state (domain 7)

Three engineers share a Terraform configuration. Which single statement is the strongest reason to use a remote backend rather than local state?

Answer: B. The defining reasons for a remote backend on a team are a shared state everyone reads/writes and locking so two applys cannot run at once and corrupt the file. A is false — remote state does not make apply faster (it can add a little latency). C is false: modules work fine with local state. D is false: local state stores outputs perfectly well. The exam wants you to connect “team” → “remote + locking”, and to not be tempted by plausible-sounding but incorrect benefits.

Q7 — workspaces (domain 4)

Which statement about CLI workspaces (terraform workspace) is correct?

Answer: B. A workspace gives you a separate state instance for the same configuration and same backend — you switch with terraform workspace select and Terraform stores each workspace’s state under a distinct key. A is false: workspaces share one backend; they do not each get their own backend block. C is the trap the exam plants deliberately — HashiCorp’s own guidance is that workspaces are not ideal for strong prod/dev isolation (they share backend, credentials, and blast radius), and teams typically use separate directories/backends or a tool like Terragrunt for real environment isolation. D is false: terraform.workspace exposes the current workspace name inside the configuration. The high-value fact: workspaces ≠ environment isolation at scale.

Q8 — modules and versioning (domain 5)

When sourcing a module from the public Terraform Registry, which argument lets you pin a specific, reproducible version?

Answer: A. Registry modules are pinned with the version argument (and it supports constraints like ~> 5.1). B (ref) is how you pin a Git-sourced module (source = "git::https://…//module?ref=v5.1.2"), not a registry module — a classic “right keyword, wrong source type” distractor. C and D are not Terraform module-pinning arguments at all. The distinction the exam draws: version for the registry, ?ref= for Git.

Q9 — the dependency graph (domain 6/8)

A security group must exist before the instance that references it. You wrote vpc_security_group_ids = [aws_security_group.web.id] on the instance. What ensures correct ordering?

Answer: B. Referencing one resource’s attribute in another (aws_security_group.web.id) creates an implicit dependency; Terraform builds a dependency graph from those references and orders creation correctly without any extra directive. A is unnecessary here — depends_on is for dependencies Terraform cannot infer (e.g. a hidden side-effect with no attribute reference); adding it when an implicit dependency already exists is redundant and a mild anti-pattern. C is false: Terraform ignores file/line order and works from the graph. D is false: Terraform parallelises independent resources but strictly orders dependent ones. The exam’s point: prefer implicit dependencies; reserve depends_on for what the graph can’t see.

Q10 — variables and precedence (domain 8)

Which variable source has the highest precedence (wins when the same variable is set in several places)?

Answer: C. The -var (and -var-file) command-line flags have the highest precedence and override everything else. The order, lowest to highest, is: environment variables → terraform.tfvarsterraform.tfvars.json*.auto.tfvars (alphabetical) → -var/-var-file (last on the command line wins). D (default) is the lowest — it is only used when nothing else sets the variable. A and B sit in the middle. Memorising “command line wins, default loses” handles most precedence questions.

Q11 — HCP Terraform / Terraform Cloud (domain 9)

Which capability is provided by HCP Terraform (Terraform Cloud) but not by open-source Terraform on its own?

Answer: C. HCP Terraform adds remote execution of runs, policy-as-code enforcement (Sentinel, or OPA), a private module registry, run history, and team/governance features on top of Terraform. A and D are core CLI features available to everyone. B is the trap: open-source Terraform can store remote state in many backends (S3, Azure Blob, GCS, Consul, …) — remote state is not exclusive to HCP, even though HCP also offers it. The exam wants you to separate “things only the platform adds” (governance, remote runs, private registry) from “things plain Terraform already does”.

Q12 — outside core workflow (domain 4)

You created an S3 bucket manually in the console and now want Terraform to manage it without destroying and recreating it. What is the correct approach?

Answer: B. To bring an existing, unmanaged resource under Terraform you import it: write a resource block that matches it, then run terraform import <address> <id> (or, in Terraform 1.5+, declare an import { to = … id = … } block and apply). A is false: a bare apply does not adopt pre-existing resources — it would try to create a new bucket and conflict. C (refresh) only updates state for resources Terraform already manages; it cannot adopt a new one. D (state mv) renames/moves an address that is already in state — it has nothing to do with importing something not yet tracked. The distinction between import (bring in something new) and state mv (move something already tracked) is frequently tested.

Q13 — functions (domain 8)

Which expression safely returns the value of var.region if set, otherwise the string "ap-south-1"?

Answer: B. coalesce() returns the first non-null/non-empty argument, so it returns var.region when set and the fallback otherwise — the idiomatic “value or default”. A (try) returns the first argument that evaluates without error; it is for swallowing errors (e.g. indexing something that might not exist), not for null/empty fallback, so it is the wrong tool here even though it sometimes appears to work. C (lookup) is for maps — it returns a key’s value or a default from a map, not a scalar fallback. D is not a real Terraform function. The exam tests that you reach for coalesce for “value-or-default” and try for “expression-might-error”.

Q14 — plan behaviour (domain 6)

What does terraform plan -refresh-only do?

Answer: B. -refresh-only compares state against real infrastructure and proposes to update the state file to match reality — it is the modern, reviewable replacement for the deprecated terraform refresh, and it is how you detect drift without changing your config. A describes a normal plan. C describes (loosely) what removing config + apply would do — -refresh-only never destroys anything. D is terraform init -upgrade, unrelated. Knowing that -refresh-only reconciles state ↔ reality (not config → reality) is the point.

Q15 — provider version constraints (domain 3)

In required_providers, what does version = "~> 4.16" permit?

Answer: B. The pessimistic constraint ~> 4.16 allows the rightmost specified component to increase while the ones to its left stay fixed — so ~> 4.16 means >= 4.16, < 5.0 (4.16, 4.17, …, 4.99). Contrast ~> 4.16.0, which means >= 4.16.0, < 4.17.0. A would be version = "4.16" with =. C is what ~> 4.16.0 (three components) would mean — a common mix-up. D has no upper bound on the major version, which ~> never allows. The exam reliably tests the ~> operator and the two-component vs three-component difference.

That is a representative cross-section. If you can answer these and explain the distractors, you are tracking well. Sit at least one full-length timed practice exam (the community ones and HashiCorp’s sample questions are fine) so that pacing — roughly a minute a question — becomes automatic.

Commonly-confused topics (the marks most candidates drop)

The exam is built around a small set of distinctions that look similar and behave differently. Internalise these and you reclaim the marks that prepared-but-not-careful candidates lose.

count vs for_each

count for_each
Takes A whole number A map or set of strings
Instance address By index: res[0], res[1] By key: res["dev"], res["prod"]
Add/remove in the middle Shifts indices → destroys/recreates the tail Only the affected key changes — others untouched
Use when A fixed count of near-identical things; or a simple on/off toggle (count = var.enabled ? 1 : 0) Items keyed by a stable identifier that may grow/shrink
Feeding a list n/a Convert with toset(var.list)

The single most important takeaway: if elements can be added or removed from anywhere but the end, use for_each. Using count over a mutable list is the source of countless real-world “why did Terraform destroy half my infrastructure” incidents — and the exam knows it.

Local state vs remote state

Local state Remote state
Where terraform.tfstate on disk S3 / Azure Blob / GCS / Consul / HCP, etc.
Locking None (single-user only) Yes (prevents concurrent writes)
Sharing Not shareable safely Shared source of truth for the team
Encryption at rest Not by default Depends on backend (S3 SSE, Azure encryption, etc.)
Use when Solo experiment, learning Any team or production work

Two exam-grade facts: open-source Terraform does not encrypt local state at rest by default, and remote state’s headline benefits are sharing and locking — not speed.

taint / -replace (and what they are not)

terraform taint <addr> marks a resource for destruction-and-recreation on the next apply. It is deprecated; the modern equivalent is terraform apply -replace="<addr>", which is better because the replacement appears in the plan before you approve it. Crucially, replacement is not the same as:

Expect at least one question that hinges on state rm ≠ replacement.

Workspaces vs Terragrunt (environment isolation)

This pairing trips up experienced engineers because both relate to “managing multiple environments”, but they operate at different levels.

CLI workspaces Terragrunt
What it is A built-in Terraform feature: multiple state files for one config in one backend A third-party wrapper around Terraform
Isolation Weak — shares backend, credentials, blast radius Strong — separate backends/state per environment, DRY config, dependencies
Backend config One backend, switched by workspace Generated per-unit; different state keys/accounts
Inter-environment deps Not handled dependency/dependencies blocks pass outputs
HashiCorp’s stance Fine for light variation; not recommended as the primary prod/dev isolation mechanism at scale (Not a HashiCorp product; see the Terragrunt lesson)

For the exam, the load-bearing fact is about workspaces: they give you multiple state files for one configuration, and HashiCorp explicitly cautions that they are not the right tool for strong production isolation. Terragrunt itself is out of scope for the Associate exam (it is a third-party tool) — but understanding the contrast cements why workspaces fall short, which is exactly what a workspace question is testing.

Implicit vs explicit dependencies

The exam wants you to choose the minimal correct mechanism: reach for depends_on only when there is no attribute to reference.

A few more high-frequency confusions

Terraform certification path

The diagram lays the Terraform Associate at the foundation of a credential ladder, then shows how the cloud DevOps professional exams (AWS DOP-C02, Azure AZ-400, Google Cloud DevOps) build on it — the same Terraform knowledge feeds every rung above.

One-page cheat sheet

Revise this the night before. If you can reproduce it from memory, you are ready.

Core workflow commands

Command Does
terraform init Download providers + modules, init backend (run first; -upgrade to bump versions)
terraform validate Check config is valid & consistent (no API calls)
terraform fmt Rewrite files to canonical formatting
terraform plan Show what apply would do (-out=plan.tfplan to save)
terraform apply Make reality match config (-auto-approve to skip prompt; apply a saved plan: apply plan.tfplan)
terraform destroy Destroy everything in state (-target to scope)
terraform output Print output values (-json, -raw)
terraform show Human-readable state or a saved plan

Outside-core-workflow commands

Command Does
terraform import <addr> <id> Bring an existing resource into state
terraform state list List addresses in state
terraform state show <addr> Show one resource’s state
terraform state mv <a> <b> Rename/move an address (refactor)
terraform state rm <addr> Forget a resource (stays in cloud, unmanaged)
terraform apply -replace="<addr>" Force destroy+recreate (modern; replaces deprecated taint)
terraform plan -refresh-only Detect drift (state ↔ reality), update state only
terraform workspace [new|select|list] Manage multiple state files for one config
terraform graph Emit the dependency graph (DOT)
terraform providers Report required providers

Meta-arguments (usable in resource/module blocks)

Meta-argument Purpose
count N instances, addressed by index
for_each One instance per map/set element, addressed by key
depends_on Explicit ordering Terraform can’t infer
provider Select a non-default (aliased) provider
lifecycle create_before_destroy, prevent_destroy, ignore_changes, replace_triggered_by

Functions worth memorising

Function Use
coalesce(a, b, …) First non-null/empty (value-or-default)
try(a, b, …) First that evaluates without error
lookup(map, key, default) Map value or default
merge(m1, m2, …) Combine maps
concat(l1, l2, …) Combine lists
toset(list) List → set (to feed for_each)
length(x) Count of list/map/string
join / split Strings ↔ lists
file() / templatefile() Read/render a file
jsonencode / jsondecode To/from JSON
cidrsubnet / cidrhost Subnet/host maths

Variable precedence (low → high)

env (TF_VAR_*)terraform.tfvars*.tfvars.json*.auto.tfvars (alphabetical) → -var / -var-file (command line; last wins). default in the block is the fallback when nothing sets it.

Version constraint operators

= 1.2.3 exact · >=, <=, >, < bounds · != 1.2.3 exclude · ~> 1.2 means >= 1.2, < 2.0 · ~> 1.2.3 means >= 1.2.3, < 1.3.0.

State facts

Local state = no locking, single user, not encrypted at rest by default. Remote state = sharing + locking; encryption depends on the backend. State holds sensitive values in plaintext regardless of intent; sensitive = true only redacts output, not the state file.

Hands-on lab: a self-test sandbox using only the local provider

You cannot practise the exam in a lab (it is recognition/recall), but you can drill the highest-yield commands with zero cloud cost using the built-in local, random, and null providers — no credentials, no spend. This 15-minute drill exercises init, plan, apply, count/for_each behaviour, state subcommands, -replace, and -refresh-only exactly as the exam describes them.

Step 1 — scaffold. Create a working directory and a single file:

# main.tf
terraform {
  required_version = ">= 1.6.0"
  required_providers {
    local  = { source = "hashicorp/local",  version = "~> 2.5" }
    random = { source = "hashicorp/random", version = "~> 3.6" }
  }
}

variable "names" {
  type    = set(string)
  default = ["alpha", "beta", "gamma"]
}

# for_each keyed by a stable string — the exam-correct pattern
resource "local_file" "note" {
  for_each = var.names
  filename = "${path.module}/out/${each.key}.txt"
  content  = "hello ${each.key}\n"
}

resource "random_pet" "name" {
  length = 2
}

output "pet" {
  value = random_pet.name.id
}

Step 2 — the core loop. Run, observing each command’s output:

terraform init        # downloads local + random providers; note the .terraform.lock.hcl created
terraform validate    # "Success! The configuration is valid."
terraform fmt         # no change if already formatted
terraform plan        # 4 to add (3 files + 1 pet)
terraform apply -auto-approve

Expected output: three files appear under out/, and terraform output pet prints a two-word pet name. Confirm: terraform state list shows local_file.note["alpha"], ["beta"], ["gamma"], and random_pet.name.

Step 3 — prove the for_each lesson. Remove "beta" from the names default and run terraform plan. Observe that only local_file.note["beta"] is planned for destruction — the others are untouched, because for_each keys are stable. (Mentally contrast: with count, removing the middle element would churn the tail. This is Q2 made real.) Apply it.

Step 4 — drill the outside-core commands.

# Force one resource to be recreated the modern way:
terraform apply -replace="random_pet.name" -auto-approve   # pet name changes; files unaffected

# Detect drift: delete a managed file by hand, then refresh-only:
rm out/alpha.txt
terraform plan -refresh-only      # shows state reconciling to reality (file now absent)
terraform plan                    # shows it would RECREATE alpha.txt to match config

# State surgery without touching real resources:
terraform state show 'local_file.note["gamma"]'

Step 5 — Cleanup.

terraform destroy -auto-approve   # removes all managed files + pet

Then delete the directory. Cost note: zero. The local/random/null providers run entirely on your machine — no cloud account, no API calls, no spend. This is the ideal way to keep command muscle memory sharp while revising.

Common mistakes & troubleshooting

Symptom (in study or on the day) Cause Fix
Recognise the right answer but pick a distractor under time pressure Reading the stem too fast; missing “NOT”/“EXCEPT”/“Select TWO” Read the stem twice; underline qualifiers; confirm how many answers are wanted
Confusing count and for_each behaviour Treating them as interchangeable Memorise: count=index (churns tail), for_each=key (stable)
Thinking sensitive = true secures state Conflating output redaction with at-rest protection It only hides CLI output; state still holds plaintext — secure the backend
Picking terraform refresh answers Studying old material refresh is deprecated → plan/apply -refresh-only
Choosing taint as the “correct” current method Pre-1.x habits taint is deprecated → apply -replace=
Believing remote state is required for modules Over-association Modules work with local state; remote state is about sharing+locking
Assuming state rm deletes the cloud resource Misreading the command state rm only forgets it; destroy/console deletes it
Mixing up ~> 1.2 and ~> 1.2.3 Skimming the constraint operator Two components → < 2.0; three components → < 1.3.0
Running out of time No pacing practice One mark/minute; flag and skip hard ones, return at the end

Best practices for passing (and for the job)

Security notes

A few security facts are themselves exam-testable and job-critical, so they earn their own section:

Interview & exam questions

A blend of likely exam items and the interview questions that probe the same knowledge — with concise answers.

  1. What does terraform init do, and why must it run first? Downloads providers (per required_providers) and modules, and initialises the backend. Without it, plan/apply have no plugins and no backend, so they cannot run.
  2. count vs for_each — when does count bite you? When you add/remove an element anywhere but the end of a list: indices shift and Terraform destroys/recreates the tail. Use for_each (keyed by a stable string) for collections that change.
  3. Why secure the state backend even if you never store passwords? State holds sensitive resource attributes (generated passwords, connection strings) in plaintext regardless of intent. Encrypt and access-control the backend.
  4. Difference between terraform taint and terraform apply -replace? Same effect (force destroy+recreate), but taint is deprecated; -replace is current and shows the replacement in the plan before you approve.
  5. What’s the modern way to detect drift? terraform plan -refresh-only — it reconciles state with real infrastructure and proposes to update state, replacing the deprecated terraform refresh.
  6. Implicit vs explicit dependencies? Implicit dependencies come from attribute references and are preferred; depends_on is for ordering Terraform cannot infer. Overusing depends_on is an anti-pattern.
  7. Are CLI workspaces a good prod/dev isolation mechanism? Not at scale — they share a backend, credentials, and blast radius. HashiCorp recommends separate directories/backends (or a tool like Terragrunt) for strong isolation.
  8. What does sensitive = true actually protect? It redacts a value from CLI output so it doesn’t leak into logs — it does not encrypt or remove the value in the state file.
  9. How do you bring an existing, manually-created resource under Terraform? Write a matching resource block, then terraform import <addr> <id> (or a 1.5+ import block + apply). A bare apply would try to create a duplicate.
  10. What does ~> 4.16 allow, and how does ~> 4.16.0 differ? ~> 4.16 = >= 4.16, < 5.0; ~> 4.16.0 = >= 4.16.0, < 4.17.0. The rightmost specified component is the one allowed to increase.
  11. What does HCP Terraform add over open-source? Remote runs, policy-as-code (Sentinel/OPA), a private module registry, run history, and governance — note remote state alone is not exclusive to HCP.
  12. Variable precedence, lowest to highest? default < environment (TF_VAR_*) < terraform.tfvars/.json < *.auto.tfvars < -var/-var-file (command line wins; last one on the line wins).

Quick check

  1. You remove the middle element from a list used by count. What does Terraform plan to do?
  2. Which command is the current replacement for terraform taint?
  3. Does sensitive = true encrypt the value in the state file?
  4. What does ~> 1.4 permit as a version range?
  5. Which has higher precedence: a -var flag or terraform.tfvars?

Answers

  1. Destroy and recreate every element from the removed index onward (and destroy the now-surplus last index), because count addresses by index and the indices shift. for_each would have changed only the affected element.
  2. terraform apply -replace="<address>" (plan -replace to preview).
  3. No — it only redacts the value from CLI output (plan/apply/output); the value remains in plaintext in state. Secure the backend.
  4. >= 1.4, < 2.0 — the pessimistic operator lets the rightmost specified component (here the minor) increase up to the next major.
  5. The -var command-line flag — command-line variables have the highest precedence and override terraform.tfvars.

Exercise

Block out a one-week sprint to the exam and execute it:

  1. Self-assess (day 1). Sit a full-length timed practice exam cold. Record your score per objective domain.
  2. Target the gaps (days 2–4). For every domain under ~80%, do the matching course lesson and run the relevant part of the lab above. Pay special attention to domains 4, 7, and 8.
  3. Drill the confusions (day 5). Re-derive the “commonly-confused” tables from memory: count/for_each, local/remote state, taint/-replace, workspaces/Terragrunt, implicit/explicit deps. If you can reproduce them, you own them.
  4. Memorise the cheat sheet (day 6). Reproduce the one-pager from a blank page until it is automatic.
  5. Dress rehearsal (day 7). Sit a second timed practice exam at the same time of day you’ve booked the real one. Aim for ≥85% with time to spare. Book the exam.

Deliverable: a filled-in score-by-domain table from days 1 and 7, plus your hand-written cheat sheet — proof you can recall it under pressure.

Certification mapping

The Terraform Associate is the credential this whole course leads to, and it also underpins a wider DevOps credential path. Terraform shows up directly or indirectly in several cloud DevOps exams:

Certification Where Terraform fits
HashiCorp Certified: Terraform Associate (003) The target of this lesson — the canonical Terraform credential
AWS Certified DevOps Engineer – Professional (DOP-C02) IaC is a core domain; Terraform (alongside CloudFormation/CDK) is expected fluency
Microsoft Certified: DevOps Engineer Expert (AZ-400) Tests IaC in pipelines; Terraform is a first-class option on Azure DevOps/GitHub
Google Cloud Professional Cloud DevOps Engineer IaC and automation feature throughout; Terraform is Google’s recommended multi-cloud IaC
HashiCorp Certified: Terraform Authoring & Operations Professional The next-level HashiCorp exam — deeper authoring, modules, and operations beyond the Associate

For a consolidated, exam-by-exam study plan across the cloud DevOps and Kubernetes certifications (with the same objective-checklist treatment), see the DevOps certification prep kit.

Glossary

Next steps

This is the final lesson of the KloudVin Terraform Zero-to-Hero course — congratulations on reaching it. From here:

TerraformCertificationHashiCorpTerraform AssociateExam PrepIaC
Need this built for real?

Vinod is a Senior Cloud Architect (22+ yrs) — available for Azure / AWS / GCP architecture, landing zones, and migrations.

Work with me

Comments

Keep Reading