Terraform

Terraform Exam Sample Questions: Question Formats Across Key Domains (Associate / Pro)

2026-04-19
NicheeLab Editorial Team
Table of contents
  1. Terraform Workflow Fundamentals and Question Patterns
  2. State and CLI Command Question Trends
  3. State Management and Backend Comparison (Associate / Pro)
  4. Designing Modules, Variables, and Outputs
  5. Resource Lifecycle, Dependencies, and Provisioners
  6. Workspaces, Policy, and Import Pitfalls
  7. Check Your Understanding
  8. Frequently Asked Questions

Terraform exams care less about memorizing commands and more about whether you understand state management and the safety of changes.

Many questions map directly to real-world pitfalls: concurrent runs, missing backend configuration, breaking changes in modules, and misuse of -target to cut dependencies.

Terraform Workflow Fundamentals and Question Patterns

Associate-level questions test whether you can explain the roles of plan/apply/destroy and what a plan is based on (the .tf declarations, the current tfstate, and the diff against real infrastructure). The Pro exam adds team-operation scenarios such as reviews, concurrent runs, and CI integration.

Classic gotchas include believing plan produces side effects, or not knowing that -refresh-only can surface drift without changing configuration.

  • terraform plan only proposes changes — no side effects.
  • terraform apply executes the plan. Overusing -auto-approve is risky.
  • -refresh-only updates only the state from real infrastructure. It does not create or destroy resources.
  • Diffs come from three sources: declarations, state, and real infrastructure. If any of them drift, the plan changes.

How plan/apply interact with remote state and locking

Developer CLI        Remote Backend (S3/Azure/GCS)        Provider API
      |                           |                           |
      | terraform plan            |                           |
      |-------------------------->|  read: tfstate            |
      |                           |-------------------------->|
      |                           |<--------------------------|
      |<--------------------------|  fetch the state the plan needs |
      |                           |                           |
      | terraform apply           |                           |
      |-------------------------->|  acquire the lock (DynamoDB etc.) |
      |                           |=== LOCK ===               |
      |                           |-------------------------->|
      |                           |<--------------------------|
      |<--------------------------|  write the state after applying |
      |                           |--- UNLOCK --------------- |

Minimal configuration example (observe plan diffs via outputs)

terraform {
  required_version = ">= 1.0"
}

variable "project_name" {
  type    = string
  default = "demo"
}

locals {
  tag = "app-${var.project_name}"
}

output "tag_example" {
  value = local.tag
  sensitive = false
}

# Change var.project_name, compare the plan, and understand the diff before applying

State and CLI Command Question Trends

State is not just a cache — it is the source of truth for the objects Terraform creates and manages. Manual edits are discouraged; the state subcommand is the safe way to manipulate it.

Associate questions cover the basics of state list/show/mv/rm and import. Pro questions lean into drift reconciliation, selective migration, and standardized procedures for team operations.

  • state list: list every address under management
  • state show: inspect a single resource's attributes (watch out for sensitive values)
  • state mv: move addresses, useful when refactoring into modules
  • state rm: removes from management without deleting the real resource
  • import: pulls existing resources into state — but does not generate configuration

CLI command examples

# List the managed resources
terraform state list

# Details of a single resource (ID and attributes)
terraform state show aws_s3_bucket.logs

# Moving addresses as part of modularization
terraform state mv aws_s3_bucket.logs module.storage.aws_s3_bucket.logs

# Import an existing VPC (the ID is the real resource identifier)
terraform import aws_vpc.main vpc-0abc1234def567890

# Drift check only
terraform plan -refresh-only

State Management and Backend Comparison (Associate / Pro)

A remote backend provides a single source of truth and locking, and is a prerequisite for team operations. When using S3, it is easy to forget DynamoDB-based locking — and without it, concurrent applies cause destructive conflicts.

Exam questions routinely ask which backends support locking, how encryption and permission models differ, and which configuration traps are easy to fall into.

  • local is for solo use — avoid it in team operations
  • Choose by comparing locking, encryption, authentication, and permission separation
  • When using S3, design versioning, SSE, and DynamoDB locking as a package
BackendLockingEncryption at RestAuth / Permissions Model
S3 (+ DynamoDB)Lockable via DynamoDBSSE-S3/KMSIAM roles / policies
azurerm (Blob)Native lockingStorage default encryptionAzure AD + RBAC
gcsGenerations + lockingServer-side encryptionService accounts + IAM
localNoneOptionalLocal permissions

S3 backend (with DynamoDB locking)

terraform {
  backend "s3" {
    bucket         = "tfstate-prod"
    key            = "network/terraform.tfstate"
    region         = "ap-northeast-1"
    dynamodb_table = "tfstate-lock"
    encrypt        = true
  }
}

# Prepare an S3 bucket (versioning on) and a DynamoDB table (partition key: LockID) first

Designing Modules, Variables, and Outputs

Associate questions focus on module invocation and passing variables and outputs. Pro questions cover version pinning, for_each vs. count, input validation, and resisting the urge to over-generalize.

Key stability is critical for for_each. To avoid destroys, use immutable keys tied to the entity (such as a name).

  • Pin module versions (via ref or the registry's version)
  • Make input boundaries explicit with variable validation
  • Keep outputs minimal, with the consumer's needs in mind
  • Switching between count and for_each can be destructive

Module invocation and input validation example

module "vpc" {
  source  = "git::https://example.com/terraform-modules.git//vpc?ref=v1.4.2"
  name    = var.project
  cidr    = var.cidr
  azs     = var.azs
}

variable "project" {
  type = string
  validation {
    condition     = length(var.project) <= 12
    error_message = "project must be 12 characters or fewer."
  }
}

variable "cidr" {
  type = string
}

output "vpc_id" {
  value = module.vpc.id
  sensitive = false
}

Resource Lifecycle, Dependencies, and Provisioners

Lifecycle controls help avoid destructive changes, but overusing them adds complexity. Prefer implicit dependencies (via references) and reach for depends_on only when necessary.

Provisioners are a last resort. Prefer cloud-native configuration mechanisms (User Data, launch templates, etc.) or external tools instead.

  • prevent_destroy guards critical resources against accidental deletion
  • create_before_destroy reduces downtime during replacement
  • replace_triggered_by makes replacement conditions explicit
  • Watch out for circular dependencies with depends_on
  • Provisioners easily become a breeding ground for retry failures and drift

Lifecycle and dependency example

resource "aws_launch_template" "app" {
  name_prefix   = "app-"
  image_id      = var.ami
  instance_type = var.instance_type

  lifecycle {
    create_before_destroy = true
    prevent_destroy       = false
  }
}

resource "aws_autoscaling_group" "asg" {
  name                = "app-asg"
  desired_capacity    = 3
  max_size            = 5
  min_size            = 3
  launch_template {
    id      = aws_launch_template.app.id
    version = "$Latest"
  }
  depends_on = [aws_launch_template.app]
}

# Initialize with user data at boot instead of a provisioner

Workspaces, Policy, and Import Pitfalls

Workspaces separate state for the same configuration across environments, but they are not a full security boundary. The recommended approach is to separate buckets and permissions per environment.

Policy tools (such as Terraform Cloud Sentinel or OPA) put guardrails in front of dangerous changes and block them before review.

import associates an existing resource with state. It does not generate configuration files, so you must define the matching resource block in advance.

  • Workspaces switch between states. The key is your strategy for separating variables and backends.
  • Policy checks make plan-time failures happen early
  • After import, run plan to confirm a zero diff. Add any missing attributes to the configuration.

Workspace and import examples

# A workspace per environment
terraform workspace new staging
terraform workspace select staging

# Import an existing resource
# Define the matching resource block first
terraform import aws_iam_role.app_role app-role

# Sentinel/OPA are usually hooked into the plan during CI or remote runs

Check Your Understanding

Associate / Pro

Question 1

Your team uses an S3 backend, but occasional concurrent terraform apply runs have nearly corrupted the state file. Which is the most appropriate remediation?

  1. Provision a DynamoDB table alongside S3 and enable locking in the backend configuration
  2. Specifying a longer -lock-timeout on terraform apply is sufficient
  3. Creating multiple workspaces to split the same environment will prevent conflicts
  4. Commit the state file to Git and resolve conflicts via merge strategy

Correct answer: A

The S3 backend on its own does not provide locking, so enabling locking with a companion DynamoDB table is correct. -lock-timeout only adjusts the wait time; it is not a substitute for a locking mechanism. Workspaces separate state but do not solve concurrent updates to the same environment. Managing tfstate in Git is discouraged.

Frequently Asked Questions

What is the main difference between terraform plan and apply?

plan only proposes changes with no side effects. apply executes the plan and actually modifies real infrastructure. Reviews and policy checks run against the plan output.

When is it appropriate to use -target?

Reserve it for emergency, narrowly scoped changes such as incident response. Because it ignores parts of the dependency graph, avoid it in routine operations or normal change workflows.

How should sensitive values and credentials be handled?

Use environment variables, the Terraform Cloud variable store, or each cloud's secret manager. Never leave plaintext in tfvars or state files, and minimize exposure with sensitive outputs.

Check what you learned with practice questions

Practice with certification-focused question sets

Try free questions
Author

NicheeLab Editorial Team

NicheeLab editorial team focused on data engineering and cloud certification learning. Content is structured around practical study needs and official exam domains.


Related articles
Terraform

HCL Syntax: Terraform's Configuration Language (2026)

HCL2 fundamentals for Terraform — blocks, attributes, expres...

Terraform

Terraform Authoring & Operations Pro: Complete Guide (2026)

Tactics for the Terraform Pro exam — module authoring, works...

Terraform

Terraform Providers: Plugin Management Fundamentals (2026)

Provider mechanics — required_providers, versions, mirrors, ...

Terraform

Terraform Resource Blocks: Declarative Infra Units (2026)

Resource block fundamentals — addresses, references, common ...

Terraform

Terraform Data Sources: Read-Only External Data (2026)

Data source basics — declaration, refresh behavior, dependen...

Browse all Terraform articles (102)
© 2026 NicheeLab All rights reserved.