HashiCorp Terraform Associate (003) — Frequently Asked Questions

Deep-dive FAQ for the Terraform Associate (003) exam: format & scope, versions and tooling, workflow/state/backends, variables/modules, providers/auth, import/replace/drift, workspaces vs separate state, CI/CD, policy-as-code, and exam-day tips.

What does the Terraform Associate (003) exam cover?

Core Terraform fundamentals: the workflow (init → plan → apply → destroy), state & backends, variables/outputs/locals, providers & auth, modules & versioning, workspaces, import/replace/refresh-only, basic policy-awareness, and safe practices (review plans, least privilege, secrets handling). It’s tooling- and vendor-neutral (AWS/Azure/GCP examples appear, but you’re tested on Terraform behavior).


Who is this exam for?

Cloud/DevOps/platform engineers, SREs, and developers who write or review Terraform. If you can read plans, reason about state/backends, and build small modules safely, you’re ready to prep.


Is there a specific Terraform version on the exam?

Expect mainstream Terraform 1.x behaviors and terminology used in current docs. Pin a recent 1.x locally and avoid legacy mental models (e.g., prefer -replace over tainting).


What’s the exam format? How many questions?

Multiple-choice/single- and multi-select questions (with realistic code snippets and CLI scenarios). CompTIA-style PBQs are not the norm; still, be ready to interpret small HCL fragments and plans quickly.


How should I study, and for how long?

Typical: 2–4 weeks with short labs. Daily cadence:

  • 30–45 minutes reading the Syllabus objectives
  • 20–25 practice questions (domain-focused)
  • Convert misses into 2-bullet rules, then re-drill within 24–48 hours
    Do 1–2 full mocks in the final week.

What should I memorize vs understand?

Memorize command shapes and var precedence; understand why we prefer for_each over count for stable addressing, when to use workspaces vs separate state, and how backends/locking prevent collisions.


What’s the canonical workflow again?

1terraform init
2terraform fmt -recursive
3terraform validate
4terraform plan
5terraform apply
6terraform plan -destroy
7terraform destroy

Know when to add flags (e.g., -var-file, -out, -replace, -refresh-only).


How do backends and state locking work?

  • State maps config ↔ real resources; keep it secure and backed up.

  • Remote backends centralize state and enable locking:

    • AWS: S3 (+ DynamoDB table for locks)
    • Azure: azurerm (blob storage)
    • GCP: gcs
  • Initialize or reconfigure with terraform init and -backend-config flags. Never hand-edit state unless you’re performing a surgical recovery.


Should I use workspaces or separate states?

  • Workspaces = multiple state instances for the same config (e.g., dev, stage, prod). Good for light envs that share topology.
  • Separate states/backends = stronger isolation (common for real prod vs non-prod, or different regions/accounts). If in doubt for production: separate state per environment/region/account.

What’s the difference between count and for_each?

  • count → index-based (resource[0]), can reshuffle addresses when list order changes.
  • for_each → key-based (map/set), stable addressing, fewer surprises on updates. Prefer for_each for collections with meaningful keys.

Example

1resource "aws_iam_user" "user" {
2  for_each = toset(["alice", "bob"])
3  name     = each.key
4}

How do I pin versions for Terraform and providers/modules?

 1terraform {
 2  required_version = "~> 1.8"
 3  required_providers {
 4    aws = { source = "hashicorp/aws", version = "~> 5.0" }
 5  }
 6}
 7module "vpc" {
 8  source  = "terraform-aws-modules/vpc/aws"
 9  version = "~> 5.0"
10}

Commit .terraform.lock.hcl to keep provider versions consistent across devs/CI.


Best way to handle secrets and sensitive values?

  • Mark variables/outputs as sensitive = true (prevents UI echo).
  • Prefer cloud-native secret stores (e.g., SSM Parameter Store, Secrets Manager, Key Vault, Secret Manager).
  • Avoid storing plaintext secrets in state; use data sources or runtime injection.

How do I import existing resources?

Two flows:

A) Import blocks (preferred when supported)

1resource "aws_s3_bucket" "logs" { bucket = "my-logs" }
2
3import {
4  to = aws_s3_bucket.logs
5  id = "my-logs"
6}
1terraform plan
2terraform apply

B) Legacy CLI

1terraform import aws_s3_bucket.logs my-logs

Then add matching HCL if it wasn’t present and apply.


When should I use -replace?

When you intend to recreate a resource (e.g., pet VM with drift, or immutable replacement):

1terraform plan  -replace=aws_instance.app
2terraform apply -replace=aws_instance.app

Prefer this over the old taint workflow.


What is -refresh-only, and when do I use it?

To detect/report external drift without proposing changes:

1terraform plan  -refresh-only
2terraform apply -refresh-only

Great for reconciling state with reality before deciding your next step.


Is -target safe?

Use sparingly. It can bypass the intended DAG and leave infra half-updated. Prefer architectural fixes or staged applies over frequent targeting.


How do I keep plans safe and auditable?

  • Generate a binary plan and review:
1terraform plan -out=plan.bin
2terraform show plan.bin
3terraform apply plan.bin
  • Code review PRs for HCL + plan artifacts.
  • Enforce least privilege on provider credentials and backends.

How does CI/CD fit in?

  • Run fmt/validate and plan on PR; gate apply on approval.
  • Use the same backend and commit the lock file to keep provider versions aligned.
  • For multi-env, parameterize -var-file and consider separate states/backends per environment.

Do I need Terraform Cloud/Enterprise knowledge?

Awareness helps: remote runs, remote state, workspaces, variables, and policy-as-code (Sentinel). You should recognize the concepts even if you don’t use them daily.


What’s policy-as-code (Sentinel/OPA) at Associate level?

Recognize that policies evaluate plans/applies for compliance (tagging, regions, cost, security). Sentinel is native to Terraform Cloud/Enterprise; OPA/Rego is a common ecosystem alternative.


Provider authentication — quick pointers?

AWS

1provider "aws" {
2  region  = var.region
3  profile = var.aws_profile
4}

Env vars: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN, AWS_PROFILE.

Azure

1provider "azurerm" { features {} }

Use az login or a service principal: ARM_CLIENT_ID, ARM_CLIENT_SECRET, ARM_TENANT_ID, ARM_SUBSCRIPTION_ID.

GCP

1provider "google" {
2  project = var.project
3  region  = var.region
4}

ADC via gcloud auth application-default login or GOOGLE_APPLICATION_CREDENTIALS.


Variables: what’s the precedence order?

Highest → lowest:

  1. CLI -var / later -var-file
  2. *.auto.tfvars (alphabetical)
  3. terraform.tfvars / .tfvars.json
  4. Env TF_VAR_name
  5. Variable default

Why do my resources keep recreating?

Common causes: changing keys with for_each, lack of stable identifiers, provider bugs, or lifecycle changes. Use stable keys, consider lifecycle.ignore_changes for externally managed fields, and pin versions.


When do I use create_before_destroy?

When a resource must exist before replacing the old (e.g., load balancers, launch templates):

1lifecycle {
2  create_before_destroy = true
3}

Pair with outputs and depends-on as needed to keep traffic flowing.


Can I mix provisioners and cloud-init?

Prefer cloud-init/user-data or proper config mgmt. Provisioners are last resort (network reachability, idempotency risks).


Naming & structure: modules vs monoliths?

Break into small, composable modules with good READMEs and version pinning. Keep env-specific values in var files and use outputs for wiring across modules.


Exam-day tips

  • First pass fast; flag long stems.
  • Read the final ask before parsing code; zoom in on the relevant block/flag.
  • Prefer safe, auditable workflows (reviewed plans, version pinning, remote state + locking).
  • Choose for_each over count for stable addressing; -replace for intentional recreation; -refresh-only for drift checks; use -target sparingly.
  • If two answers work, pick the one that’s least risky, more automatable, and closer to Terraform best practices.

Quick readiness checklist

  • I can explain state, backends, and locking, and configure S3/DynamoDB or azurerm/gcs.
  • I know var precedence, can write validation, sensitive, locals, and outputs.
  • I can choose for_each vs count and avoid address churn.
  • I can import existing resources and intentionally replace with -replace.
  • I can detect drift with -refresh-only and know when not to use -target.
  • I pin versions, commit the lock file, and review plans before apply.
  • I can justify workspaces vs separate state and outline a simple CI flow.