Skip to content
RED SAGSkills

Terraform interview questions and answers

Terraform questions test infrastructure as code: state, modules and making changes safely.

Below are 51 Terraform questions with the correct answer and a short explanation, grouped from fresher to experienced level. Try each one before you open the answer.

What Terraform interviews usually check

  • ✓Providers, resources and data sources
  • ✓State and remote backends
  • ✓Modules and reuse
  • ✓plan, apply and drift
  • ✓Secrets and safe changes

Terraform interview questions for freshers easy

1. What terraform plan does

What does terraform plan do?

  1. A.Creates all resources in the cloud immediately.
  2. B.Downloads provider plugins and sets up the backend.
  3. C.Compares the configuration with the current state and real infrastructure, and shows what changes would be made without applying them.
  4. D.Deletes the state file so Terraform can start fresh.
Show answer

Answer: C. Compares the configuration with the current state and real infrastructure, and shows what changes would be made without applying them.

terraform plan refreshes state, compares it with your configuration and prints the create, update and destroy actions it would take. Nothing is changed. terraform init downloads providers and configures the backend, and terraform apply actually makes the changes.

2. What terraform init does

What does terraform init do in a new working directory?

  1. A.Creates all resources in the configuration in dependency order.
  2. B.Deletes any existing state file so the directory starts fresh.
  3. C.Formats every .tf file and validates the syntax of the code.
  4. D.Downloads providers and modules and configures the state backend.
Show answer

Answer: D. Downloads providers and modules and configures the state backend.

terraform init prepares a directory: it installs provider plugins (respecting the lock file), downloads modules, and sets up the backend where state lives. It does not create or change any infrastructure. You run it again when you add providers, modules or change backend settings. Formatting is terraform fmt.

3. Why Terraform keeps state

Why does Terraform need a state file?

  1. A.It stores a copy of the Terraform binary so every user runs the same version.
  2. B.It holds the full CI pipeline logs and the saved plan output from every previous apply run in the team.
  3. C.It maps resources in your code to real cloud objects, so Terraform can plan changes.
  4. D.It is only a local cache, so it can be deleted at any time without any effect.
Show answer

Answer: C. It maps resources in your code to real cloud objects, so Terraform can plan changes.

State records which real resource ID belongs to each resource address in your configuration, plus attributes and dependencies. Terraform compares code, state and real infrastructure to build a plan. Losing state means Terraform no longer knows it manages those objects, and state can contain secrets, so it must be stored securely.

4. What IaC scanning catches

A Terraform PR adds a security group allowing 0.0.0.0/0 on port 22. Which pipeline check is designed to flag this before it is applied?

  1. A.A unit test suite for the application code
  2. B.A DAST scan of the live production website
  3. C.An IaC scanner such as Checkov, tfsec or Trivy config
  4. D.A vulnerability scan of the container image
Show answer

Answer: C. An IaC scanner such as Checkov, tfsec or Trivy config

IaC scanners read Terraform, CloudFormation, Kubernetes YAML and similar files and check them against rules like "no SSH open to the internet" or "storage must be encrypted". Running them on PRs catches misconfigurations before any resource exists. Application and image scans do not read infrastructure code.

5. Resource block vs data block

What is the difference between a resource block and a data block in Terraform?

  1. A.A resource is read-only; a data block creates new objects in the cloud
  2. B.They are the same thing; data is an older name for resource
  3. C.A resource is managed by Terraform; a data block only reads existing things
  4. D.A resource is stored in state; a data block is never evaluated during plan
Show answer

Answer: C. A resource is managed by Terraform; a data block only reads existing things

Resource blocks describe objects Terraform creates, updates and destroys. Data blocks look up existing information, such as the latest AMI or an existing VPC, and expose it for use elsewhere. Terraform never destroys what a data source reads.

6. What terraform fmt does

A reviewer asks you to run terraform fmt before pushing. What will it do?

  1. A.Rewrite .tf files into the standard layout and indentation
  2. B.Remove unused variables and outputs from the code
  3. C.Check that every resource argument has a valid value
  4. D.Format the state file so it is easier to read
Show answer

Answer: A. Rewrite .tf files into the standard layout and indentation

terraform fmt only changes whitespace and layout to match the canonical HCL style, so diffs stay clean. It does not check logic. In CI, terraform fmt -check fails the build if any file is not formatted.

7. What terraform validate checks

What does terraform validate check?

  1. A.That the real infrastructure matches the state file
  2. B.That the code is valid HCL with correct names, types and references
  3. C.That the plan will apply without any API errors
  4. D.That the cloud account has enough quota for every resource
Show answer

Answer: B. That the code is valid HCL with correct names, types and references

terraform validate checks syntax, references, argument names and types without calling cloud APIs. It cannot know whether an apply will succeed, because quotas, permissions and name clashes are only found when the provider calls the API. It needs terraform init first so provider schemas are available.

8. Which tfvars files load automatically

Which variable file does Terraform load automatically without a -var-file flag?

  1. A.prod.tfvars in the working directory
  2. B.Any .tfvars file in a parent directory
  3. C.terraform.tfvars in the working directory
  4. D.variables.tf in the working directory
Show answer

Answer: C. terraform.tfvars in the working directory

Terraform automatically loads terraform.tfvars, terraform.tfvars.json and any file ending in .auto.tfvars in the working directory. A name like prod.tfvars needs -var-file=prod.tfvars. variables.tf normally holds variable declarations, not values.

9. Setting a variable from the environment

A module declares variable "region". How can a CI job set it through an environment variable?

  1. A.Export REGION with the value
  2. B.Export TF_VAR_region with the value
  3. C.Export TERRAFORM_REGION with the value
  4. D.Export TF_REGION_VAR with the value
Show answer

Answer: B. Export TF_VAR_region with the value

Terraform reads environment variables named TF_VAR_ followed by the variable name, so TF_VAR_region sets var.region. This is handy in CI where values come from pipeline settings. Values set with -var or tfvars files take precedence over TF_VAR_ variables.

10. What a Terraform module is

What is a Terraform module?

  1. A.A single resource block with its lifecycle settings
  2. B.A folder of .tf files you call with inputs to reuse
  3. C.A saved plan file that can be applied later
  4. D.A plugin binary that talks to one cloud provider
Show answer

Answer: B. A folder of .tf files you call with inputs to reuse

Any directory of Terraform files is a module; the directory you run commands in is the root module. Calling a module with a module block lets you reuse the same set of resources with different inputs. Modules expose results through output values.

11. What ~> 5.0 allows

A provider is pinned with version = "~> 5.0". Which versions are allowed?

  1. A.5.0.x patches only, not 5.1
  2. B.5.0 and any later 5.x, but not 6.0
  3. C.Only exactly 5.0.0
  4. D.Any version from 5.0 upward, including 6.x
Show answer

Answer: B. 5.0 and any later 5.x, but not 6.0

The ~> operator allows only the right-most stated part to increase. With ~> 5.0 the minor number can grow, so 5.1 or 5.80 are fine, but 6.0 is not. Writing ~> 5.0.3 would allow only 5.0.x patches from 5.0.3 up.

12. What a Terraform backend is

In Terraform, what does the backend decide?

  1. A.Which provider versions are downloaded
  2. B.Where state is stored and how it is locked
  3. C.Which cloud region resources are created in
  4. D.Which machine runs the providers
Show answer

Answer: B. Where state is stored and how it is locked

The backend block in the terraform block sets where state lives, such as a local file, S3, Azure Blob, GCS or HCP Terraform, and whether it supports locking. Regions belong to providers, and versions to required_providers. Changing backend needs terraform init again.

13. What not to commit in a Terraform repo

Which of these should normally be listed in .gitignore for a Terraform repo?

  1. A..terraform/ and *.tfstate files
  2. B.variables.tf and outputs.tf
  3. C..terraform.lock.hcl
  4. D.versions.tf
Show answer

Answer: A. .terraform/ and *.tfstate files

The .terraform folder holds downloaded providers and modules and is rebuilt by init. State files can contain secrets and belong in a remote backend, not Git. The lock file should be committed so every run uses the same provider versions.

14. Reading -/+ in a plan

A plan line starts with -/+ in front of a resource. What does it mean?

  1. A.The resource will be destroyed and then created again
  2. B.The resource will be read but not changed
  3. C.The resource will be removed from state only
  4. D.The resource will be updated in place
Show answer

Answer: A. The resource will be destroyed and then created again

In plan output, + is create, - is destroy, ~ is update in place, and -/+ is replace (destroy then create). +/- means replace with the new one created first, from create_before_destroy. Look for "forces replacement" to see which argument caused it.

15. Terraform and Ansible together

A team uses Terraform and Ansible together. What is the most common split of work?

  1. A.Both create the same resources so one can back up the other
  2. B.Terraform runs only in prod; Ansible runs only in dev
  3. C.Ansible creates the cloud network; Terraform installs packages
  4. D.Terraform creates cloud resources; Ansible configures servers
Show answer

Answer: D. Terraform creates cloud resources; Ansible configures servers

Terraform is strongest at provisioning cloud objects with state and a plan. Ansible is strongest at configuring what runs inside machines: packages, files, services. With immutable images or containers, less in-server configuration is needed, but the split is still common for VMs.

16. What sets Pulumi apart

What is the main difference between Pulumi and Terraform for the person writing the code?

  1. A.Pulumi configures software inside servers
  2. B.Pulumi only works with Kubernetes clusters
  3. C.Pulumi uses languages like TypeScript, Python or Go
  4. D.Pulumi has no state, so it cannot detect drift
Show answer

Answer: C. Pulumi uses languages like TypeScript, Python or Go

Pulumi lets you write infrastructure in general-purpose languages, with normal loops, functions, packages and tests. Like Terraform it keeps state and shows a preview before changes. The flexibility is useful, but teams must keep code simple so changes stay reviewable.

17. What a Terraform output does

What is the purpose of an output block in Terraform?

  1. A.It writes the full apply log to a local file for later review
  2. B.It defines the input parameters that callers pass into a module
  3. C.It pins the provider versions used by the configuration
  4. D.It exposes a value, like a load balancer DNS name, after apply
Show answer

Answer: D. It exposes a value, like a load balancer DNS name, after apply

Outputs publish values after apply so people, scripts or parent modules can use them. Inside a module they are how you pass results back to the caller. Inputs are defined with variable blocks, and provider versions are pinned in required_providers.

Terraform intermediate interview questions medium

18. Terraform state in a team

Five engineers run Terraform against the same environment. What is the recommended way to manage state?

  1. A.Use a remote backend (for example S3 with native locking, or Terraform Cloud) with locking and encryption, and restrict who can read the state.
  2. B.Commit terraform.tfstate to Git so everyone has the latest version.
  3. C.Let each engineer keep a local state file and merge them weekly.
  4. D.Disable state with -state=/dev/null because Terraform can read the cloud directly.
Show answer

Answer: A. Use a remote backend (for example S3 with native locking, or Terraform Cloud) with locking and encryption, and restrict who can read the state.

A remote backend gives one shared source of truth, and locking prevents two applies from corrupting state at the same time. State often contains secrets, so it must be encrypted and access-controlled. Committing state to Git leaks secrets and causes conflicts, and Terraform cannot work without state.

19. Console change shows up in plan

During an incident someone raised an autoscaling group max size from 6 to 12 in the cloud console. Now terraform plan wants to set it back to 6. The team wants to keep 12. What is the right approach?

  1. A.Update the Terraform code to 12, then plan and apply so code, state and reality match again.
  2. B.Delete the resource from state with terraform state rm so Terraform stops managing it.
  3. C.Run terraform apply -auto-approve and change it back in the console afterwards.
  4. D.Add the attribute to ignore_changes permanently for every resource.
Show answer

Answer: A. Update the Terraform code to 12, then plan and apply so code, state and reality match again.

Terraform treats code as the source of truth, so drift is fixed by changing the code to the wanted value and applying, which yields a no-op or small plan. terraform plan -refresh-only helps you see drift, but only the code change keeps future applies from reverting it. state rm would orphan the resource, and blanket ignore_changes hides real drift.

20. Guarding a production database

You want Terraform to refuse any plan that would delete the production RDS instance. Which setting does this?

  1. A.create_before_destroy = true
  2. B.ignore_changes = all
  3. C.prevent_destroy = true
  4. D.replace_triggered_by = []
Show answer

Answer: C. prevent_destroy = true

prevent_destroy = true makes any plan that destroys or replaces that resource fail with an error. It does not protect against someone deleting the block itself, since then the lifecycle setting is gone too. Pair it with deletion protection on the database for real safety.

21. Many ingress rules from a list

A security group needs one ingress block per entry in var.ports. Which Terraform feature builds those nested blocks?

  1. A.A for expression inside the ingress block
  2. B.A separate module call per port
  3. C.count on the ingress block
  4. D.A dynamic "ingress" block with for_each
Show answer

Answer: D. A dynamic "ingress" block with for_each

Nested blocks like ingress cannot take count or for_each directly, so Terraform provides dynamic blocks: dynamic "ingress" { for_each = var.ports; content { ... } }. Inside content you use ingress.value. Overusing dynamic blocks hurts readability, so use them only when the list really varies.

22. Creating a resource only in prod

A WAF should exist only when var.env is "prod". Which pattern does this, and how do you refer to it?

  1. A.enabled = var.env == "prod", then use aws_wafv2_web_acl.x
  2. B.lifecycle { create = var.env == "prod" }, then use aws_wafv2_web_acl.x
  3. C.count = var.env == "prod" ? 1 : 0, then use aws_wafv2_web_acl.x[0] or one()
  4. D.depends_on = [var.env], then use aws_wafv2_web_acl.x
Show answer

Answer: C. count = var.env == "prod" ? 1 : 0, then use aws_wafv2_web_acl.x[0] or one()

Setting count to 1 or 0 is the standard way to make a resource optional. Because the resource becomes a list, refer to it with [0], or with one(aws_wafv2_web_acl.x[*].id), which returns null when the list is empty. There is no generic enabled argument on resources.

23. What CLI workspaces give you

You run terraform workspace new staging and then apply. What changes compared with the default workspace?

  1. A.A new cloud account is created for staging
  2. B.The default state is locked until staging is deleted
  3. C.Terraform copies the code into a new staging folder
  4. D.The same code is applied with a separate state file for staging
Show answer

Answer: D. The same code is applied with a separate state file for staging

CLI workspaces keep several state files for one configuration, and terraform.workspace tells the code which one is active. They suit short-lived copies like feature environments. For prod vs non-prod with different accounts and permissions, many teams prefer separate directories or stacks so mistakes are harder.

24. Handing a resource to another team

Another team will manage a DNS zone from now on. You must remove it from your Terraform without deleting the zone. What is the modern way?

  1. A.Add prevent_destroy = true and delete the resource block
  2. B.Delete the resource block and add this removed block, then apply
  3. C.Delete the resource block and run terraform apply
  4. D.Run terraform destroy -target=aws_route53_zone.main
Show answer

Answer: B. Delete the resource block and add this removed block, then apply

A removed block with destroy = false (Terraform 1.7+) tells Terraform to forget the object from state while leaving it running, and it goes through normal plan and review. Simply deleting the block would plan a destroy. terraform state rm does the same forgetting but outside the reviewed plan.

25. Testing an expression quickly

You are not sure what cidrsubnet("10.0.0.0/16", 8, 2) returns. What is the quickest way to check?

  1. A.Run terraform validate -expr
  2. B.Run terraform fmt -check on the file
  3. C.Add it to a resource and run apply
  4. D.Run terraform console and type the expression
Show answer

Answer: D. Run terraform console and type the expression

terraform console is an interactive prompt that evaluates expressions, functions and even values from state. Here it returns "10.0.2.0/24", because 8 new bits make a /24 and 2 is the third block. Testing with apply is slow and risky.

26. What Atlantis does

A team adds Atlantis to their Terraform repo. What does it give them?

  1. A.It replaces the state backend with a database
  2. B.It writes Terraform code from the cloud console
  3. C.Runs plan and apply from PR comments and posts output
  4. D.It converts Terraform code into CloudFormation
Show answer

Answer: C. Runs plan and apply from PR comments and posts output

Atlantis listens to pull request events, runs terraform plan, comments the output, and runs apply when someone comments atlantis apply after approval. It also locks a directory while a PR is open. HCP Terraform, Spacelift and env0 offer similar PR-driven workflows.

27. Why teams add Terragrunt

You have 30 Terraform stacks across 3 environments, each with near-identical backend and provider blocks. What problem does Terragrunt mainly solve here?

  1. A.Generates shared backend and provider config
  2. B.It replaces providers with faster ones
  3. C.It converts Terraform into Ansible playbooks
  4. D.It removes the need for state files
Show answer

Answer: A. Generates shared backend and provider config

Terragrunt is a thin wrapper that keeps backend settings, provider blocks and common inputs in one place, generates them per stack, and can run many stacks in dependency order. It does not change how Terraform plans. The trade-off is one more tool for the team to learn.

28. What tflint adds to validate

terraform validate passes, but apply fails because instance_type = "t3.mediun" does not exist. Which tool would have caught it in CI?

  1. A.terraform fmt -check
  2. B.terraform graph
  3. C.terraform output
  4. D.tflint with the AWS ruleset
Show answer

Answer: D. tflint with the AWS ruleset

validate only checks that the value is a string. tflint with a provider ruleset knows valid instance types, deprecated arguments and naming rules, so it catches this typo before apply. Security scanners like Checkov or Trivy look at a different class of problems.

29. Showing cost before merge

Finance wants to see how much a Terraform change will add to the monthly bill before it is merged. What is a common approach?

  1. A.Add a cost tag to every resource and wait for the report
  2. B.Use terraform validate with a -cost flag
  3. C.Run Infracost on the plan and comment the cost difference on the PR
  4. D.Apply to prod and read the bill at the end of the month
Show answer

Answer: C. Run Infracost on the plan and comment the cost difference on the PR

Infracost reads the plan or code, prices resources using public cloud prices, and posts a monthly cost diff, such as "+₹42,000/month" for bigger database instances. Usage-based items like data transfer need usage estimates. Tags help track spend after the fact, not before merge.

30. Encrypting state in OpenTofu

Security wants state encrypted by the tool itself before it reaches the bucket, not just by the storage service. Which tool supports this natively?

  1. A.Terraform, with sensitive = true on all outputs
  2. B.OpenTofu, with an encryption block and KMS key
  3. C.Neither, because state cannot be encrypted
  4. D.Terraform, by turning on S3 encrypt = true
Show answer

Answer: B. OpenTofu, with an encryption block and KMS key

OpenTofu 1.7 added client-side state and plan encryption, configured in the terraform block with key providers such as AWS KMS, GCP KMS or a passphrase. S3 encrypt = true only encrypts at rest inside S3, so anyone with read access still sees plain state. Keep the key safe: losing it means losing the state.

31. Renaming a resource without recreating it

You rename aws_instance.web to aws_instance.app in your Terraform code, and plan now wants to destroy and recreate the server. How do you avoid that?

  1. A.Run terraform apply -replace=aws_instance.app
  2. B.Delete the state file and import everything again
  3. C.Mark the old resource with terraform taint
  4. D.Add a moved block from aws_instance.web to aws_instance.app
Show answer

Answer: D. Add a moved block from aws_instance.web to aws_instance.app

A moved block tells Terraform the object at the old address is now at the new address, so state is updated instead of replacing the resource. It is reviewable in code and works for modules too. terraform state mv does the same imperatively, while -replace and taint force the recreation you are trying to avoid.

32. Why define infrastructure as code

Your team builds environments by clicking in the console, and staging never quite matches production. What does infrastructure as code (Terraform, CloudFormation, Bicep) fix?

  1. A.It makes every resource cost less automatically
  2. B.It removes the need for any access control rules
  3. C.Every environment is built from the same reviewed code
  4. D.It means the cloud provider now manages your app
Show answer

Answer: C. Every environment is built from the same reviewed code

IaC describes resources in files that are reviewed, versioned and applied repeatedly, giving consistent environments and an audit trail. It does not change prices or remove the need for IAM.

33. Catching misconfigurations in Terraform

Several S3 buckets were deployed public through Terraform before anyone noticed. Where is the cheapest place to catch this next time?

  1. A.Wait for the monthly external penetration test
  2. B.Ask developers to check the console after each deploy
  3. C.Scan the Terraform plan in CI with policy-as-code checks
  4. D.Delete public buckets manually once a quarter
Show answer

Answer: C. Scan the Terraform plan in CI with policy-as-code checks

Tools like Checkov, tfsec/Trivy, OPA Conftest or Sentinel check IaC against rules before anything is created, so the pull request fails with a clear message. Detective controls like Config and Security Hub are still needed for changes made outside IaC. Catching issues earlier is cheaper and faster.

34. Unexpected changes in a plan

Nobody changed the Terraform code, but terraform plan now wants to change a security group rule back. What is the most likely explanation?

  1. A.Terraform randomly changes resources to test them
  2. B.The provider plugin was uninstalled
  3. C.Someone changed the resource outside Terraform, for example in the cloud console, causing drift
  4. D.The state file is encrypted
Show answer

Answer: C. Someone changed the resource outside Terraform, for example in the cloud console, causing drift

Plan refreshes real resource state and shows the difference from the code. A change made by hand makes the real resource drift, and Terraform proposes to undo it. Decide whether to keep the change (update the code) or revert it, and limit console write access to avoid repeats.

Terraform interview questions for experienced candidates hard

35. Removing an item from a count list

You remove "b" from the list below. terraform plan wants to destroy and recreate buckets you did not touch. Why, and what is the fix?

variable "names" { default = ["a", "b", "c"] }

resource "aws_s3_bucket" "this" {
  count  = length(var.names)
  bucket = "acme-${var.names[count.index]}"
}
  1. A.The AWS provider is outdated; upgrading it will stop the replacement.
  2. B.S3 bucket names cannot be changed, so Terraform always replaces every bucket.
  3. C.count tracks resources by index, so "c" moves from index 2 to 1 and is seen as a change; use for_each over a set or map so each bucket is keyed by its name, and use moved blocks to migrate.
  4. D.The state file is corrupted and must be deleted.
Show answer

Answer: C. count tracks resources by index, so "c" moves from index 2 to 1 and is seen as a change; use for_each over a set or map so each bucket is keyed by its name, and use moved blocks to migrate.

With count, resources are addressed as this[0], this[1], this[2]. Removing a middle item shifts later items to new indexes, so Terraform thinks this[1] must change from b to c and this[2] must be destroyed. for_each keys resources by a stable value such as the name, and moved blocks let you change addresses without recreating real infrastructure.

36. One huge Terraform state

One Terraform root module manages networking, databases, Kubernetes and 40 app stacks. Plans take 25 minutes and a typo in one app once touched the VPC. What is the best direction?

  1. A.Keep the single state but run every plan and apply with -parallelism=1 so changes go one at a time.
  2. B.Split into smaller root modules by layer and lifecycle, each with its own state, linked by outputs.
  3. C.Wrap everything in one large shared module, so the code is reused and planned in one place.
  4. D.Use -target on every apply so only the changed resources are planned and applied.
Show answer

Answer: B. Split into smaller root modules by layer and lifecycle, each with its own state, linked by outputs.

Separate states shrink the blast radius, speed up plans and let teams own and lock their own stacks. Rarely changed foundations such as the network live apart from fast-moving app stacks. The trade-off is managing dependencies between stacks, often via remote state outputs, data sources or tools such as Terragrunt or Terraform stacks. -target is an escape hatch, not a workflow.

37. Forcing one resource to be rebuilt

One VM is broken inside, though its config is fine. You want Terraform to destroy and recreate just it, with the change visible in a reviewed plan. What do you use?

  1. A.terraform apply -target=aws_instance.web -refresh=false
  2. B.terraform plan -replace=aws_instance.web
  3. C.terraform state rm aws_instance.web, then apply
  4. D.terraform taint aws_instance.web, then apply later
Show answer

Answer: B. terraform plan -replace=aws_instance.web

-replace marks the resource for replacement inside a single plan, so reviewers see it and nothing changes until apply. taint is deprecated because it changes state immediately, which can surprise teammates. state rm would make Terraform create a second VM and leave the old one orphaned.

38. Rebuilding when a related thing changes

An instance must be replaced whenever the launch script in aws_s3_object.bootstrap changes, even though the instance does not reference its content. Which feature fits?

  1. A.lifecycle { replace_triggered_by = [aws_s3_object.bootstrap] }
  2. B.depends_on = [aws_s3_object.bootstrap] on the instance
  3. C.lifecycle { ignore_changes = [aws_s3_object.bootstrap] }
  4. D.lifecycle { create_before_destroy = true } on the instance
Show answer

Answer: A. lifecycle { replace_triggered_by = [aws_s3_object.bootstrap] }

replace_triggered_by replaces the resource when any listed resource or attribute changes. depends_on only orders creation and does not force replacement. To trigger on a plain value, wrap it in a terraform_data resource and reference that.

39. for_each over a list with repeats

var.buckets is ["logs", "media", "logs"]. A resource uses for_each = toset(var.buckets). How many buckets will Terraform plan?

  1. A.1
  2. B.None, because for_each fails on duplicates
  3. C.2
  4. D.3
Show answer

Answer: C. 2

toset removes duplicates, so the set is {"logs", "media"} and two instances are planned with keys logs and media. for_each needs a set or map, which is why lists are wrapped in toset. A silent de-duplication can hide a typo, so validate inputs if repeats are a mistake.

40. depends_on on a whole module

After adding depends_on = [module.network] to module.app, most data sources inside module.app show "known after apply" and many resources now plan an update every time. Why?

  1. A.Terraform re-imports every resource inside the module
  2. B.Modules with depends_on are always replaced on each apply
  3. C.depends_on on modules disables state locking
  4. D.Its data sources now wait until module.network is applied
Show answer

Answer: D. Its data sources now wait until module.network is applied

With module-level depends_on, any pending change in module.network makes Terraform defer reading data sources in module.app to apply time. Their results become unknown, which ripples into planned updates. Prefer passing specific outputs as inputs so the graph has precise edges.

41. Sharing VPC IDs between stacks

The app stack reads the network stack with data "terraform_remote_state". Security says the app team must not read the network state. What is a good alternative?

  1. A.Publish the IDs to SSM Parameter Store and read them there
  2. B.Copy the network state file into the app repo each release
  3. C.Give the app team read access to the whole state bucket
  4. D.Merge both stacks into one state so no sharing is needed
Show answer

Answer: A. Publish the IDs to SSM Parameter Store and read them there

terraform_remote_state needs read access to the full state, which may contain secrets. Publishing just the needed values to a store like SSM, Consul or a tagged lookup, and reading them with ordinary data sources, limits access and decouples the stacks. Merging stacks undoes the reason they were split.

42. Unit testing a module cheaply

You want fast tests for a naming module in CI without creating real cloud resources. Which built-in feature fits best?

  1. A.terraform validate with a -test flag
  2. B.terraform console scripted with expect
  3. C.terraform test with command = plan and mock providers
  4. D.terraform apply in a sandbox account on every commit
Show answer

Answer: C. terraform test with command = plan and mock providers

terraform test runs .tftest.hcl files with run blocks and assertions. command = plan avoids creating resources, and mock_provider (1.7+) returns fake values so no credentials are needed. Real apply tests are still useful for integration, but are slower and cost money.

43. Splat on a for_each resource

aws_instance.web uses for_each over a map. An output uses aws_instance.web[*].id and fails. What should it use?

  1. A.aws_instance.web[0].id
  2. B.aws_instance.web.id
  3. C.values(aws_instance.web)[*].id
  4. D.aws_instance.web.*.id, the older splat form
Show answer

Answer: C. values(aws_instance.web)[*].id

With for_each the resource is a map of objects, and the [*] splat works on lists (or single values), not maps. Use a for expression or values() to get a list first. With count the resource is a list, so web[*].id works there.

44. Designing state boundaries

You are designing Terraform for network, databases and 12 app services across dev and prod. Which layout best limits blast radius?

  1. A.Separate states per env and layer, with separate credentials
  2. B.One state for everything so dependencies are always correct
  3. C.One state per developer so nobody blocks each other
  4. D.One state per resource type, shared by dev and prod
Show answer

Answer: A. Separate states per env and layer, with separate credentials

Splitting by environment and by layer (network, data, apps) means a bad change to an app cannot touch the prod VPC, and plans stay small and fast. Separate credentials per environment stop a dev pipeline from changing prod. Layers share values through outputs or a parameter store.

45. Plan after a provider major upgrade

After moving to a new major provider version, plan shows several resources to be replaced though no code changed. What is the right response?

  1. A.Apply quickly, because replacements after upgrades are always harmless
  2. B.Delete the lock file so the old version comes back
  3. C.Stop, read the upgrade guide, and adjust code or use moved blocks before applying
  4. D.Run terraform state rm on the affected resources
Show answer

Answer: C. Stop, read the upgrade guide, and adjust code or use moved blocks before applying

Major versions can rename resources, change defaults or split resources, which Terraform reads as replacements. The upgrade guide explains the needed code changes, and moved blocks or state migrations often avoid recreation. Never accept replacements of stateful resources without understanding them.

46. Bake an image or configure at boot

Auto scaling instances take 9 minutes to become healthy because Ansible installs everything at boot. Scale-out is too slow for traffic spikes. What is the best long-term fix?

  1. A.Keep more instances running so scale-out never happens
  2. B.Run Ansible with more forks on each new instance
  3. C.Raise the health check grace period to 15 minutes
  4. D.Bake a golden image with Packer and Ansible ahead of time
Show answer

Answer: D. Bake a golden image with Packer and Ansible ahead of time

Building a golden image ahead of time moves the slow install out of the scale-out path, so new instances only fetch config and secrets at boot. It also makes every instance identical. A longer grace period hides the problem, and extra idle capacity costs money every hour.

47. Looking up a resource you just created

A config creates aws_vpc.main and, in the same config, uses data "aws_vpc" filtered by its Name tag to get the ID. The first apply fails with "no matching VPC found". What is the fix?

  1. A.Move the data block above the resource in the file
  2. B.Use aws_vpc.main.id directly instead of a data lookup
  3. C.Run the first apply twice and ignore the error
  4. D.Add a sleep in a local-exec provisioner before the lookup
Show answer

Answer: B. Use aws_vpc.main.id directly instead of a data lookup

Data sources are read during plan when they can be, and at that point the VPC does not exist yet. Inside one configuration, refer to the resource attributes directly, which also gives Terraform the right dependency. Data sources are for objects managed elsewhere.

48. Continuous reconcile vs plan and apply

With Crossplane, an engineer edits a managed database in the console during an incident, and minutes later the change is undone. How does this compare with Terraform?

  1. A.Crossplane reconciles nonstop; Terraform waits for an apply
  2. B.Both tools ignore console changes by default
  3. C.Crossplane never touches resources after creating them
  4. D.Terraform reverts console changes within minutes too
Show answer

Answer: A. Crossplane reconciles nonstop; Terraform waits for an apply

Controller-based tools keep comparing desired and actual state, so drift is fixed automatically, which is great for consistency but surprising during incidents. Terraform changes things only when someone applies. Teams using reconcilers need a documented way to pause reconciliation for emergencies.

49. Two tools managing one resource

A load balancer listener is defined in Terraform, and a Kubernetes controller also edits its rules. Every apply and every controller sync undo each other. What is the right principle?

  1. A.Disable state locking so both tools can write
  2. B.Copy the controller rules into Terraform daily
  3. C.Give each field one owner and ignore it elsewhere
  4. D.Run Terraform more often so that it always wins
Show answer

Answer: C. Give each field one owner and ignore it elsewhere

Two tools writing the same fields cause endless churn and outages. Decide which system owns each resource or field; if the controller owns rules, let Terraform create only the base listener and use ignore_changes for the rest, or hand the whole listener to the controller. Write the ownership down so others do not reintroduce the fight.

50. for_each keys unknown until apply

Terraform fails with the error below. What is the right fix?

Error: Invalid for_each argument
  on main.tf line 12, in resource "aws_route53_record" "this":
  for_each = toset(aws_instance.app[*].id)
The "for_each" set includes values derived from resource attributes
that cannot be determined until apply.
  1. A.Upgrade the AWS provider to the latest major version and plan again
  2. B.Run terraform init -reconfigure so the backend reloads its state
  3. C.Key for_each by values known at plan time, like static names
  4. D.Replace for_each with a depends_on that points at the instances
Show answer

Answer: C. Key for_each by values known at plan time, like static names

for_each keys become resource addresses, so Terraform must know them during plan. Instance IDs only exist after apply, so they cannot be keys. Build the map from static input such as names and use the IDs as values instead; -target applies are only a last-resort workaround.

51. A console fix that gets undone

During an incident, someone opened a port in a security group via the console. The next terraform apply silently closes it again. What is the right practice?

  1. A.Stop using Terraform for security groups
  2. B.Never run terraform apply again
  3. C.Make the change in code, or import it, then apply
  4. D.Make every console change twice
Show answer

Answer: C. Make the change in code, or import it, then apply

Terraform makes real resources match the code, so manual changes are drift and get reverted. After an emergency change, put it in code (or import it) and review it. Run regular plans to detect drift early.

Ready to test yourself?

Take a 15-question Terraform MCQ test with a score at the end, or practise the full Terraform question bank and earn points on the leaderboard.