40 Terraform & IaC interview questions with detailed answers, sorted from basic to advanced. Free to practice, with progress saved automatically.
Terraform is an Infrastructure as Code tool that describes cloud resources in declarative configuration so changes are reviewable and repeatable. Topics include state and why it stays out of version control, plan and apply, providers, modules, variables, data sources, lifecycle rules, drift, separating environments, and who may apply changes to production.
and 14 more topics.
Infrastructure becomes reviewed, versioned, reproducible code. One repo builds staging and production the same way, and git log answers "why does this security group open port 6379". Clicking cannot answer that. Six months later nobody remembers who changed what, and staging drifts from production in…
State is the map between resource addresses in code and real provider IDs, plus an attribute snapshot from the last apply. Without state Terraform does not know which database awsdbinstance.main refers to, so an apply creates a new one instead of updating. Why it does…
The ... must be replaced lines and the -/+ marker. That is destroy then recreate, and on RDS or EBS it means data loss. Read in this order: 1. The summary line: Plan: 2 to add, 1 to change, 3 to destroy. — a non-zero…
No. A provider is a plugin translating resource blocks into one service API, and resources differ completely per cloud. awsinstance does not run on GCP — switching clouds means rewriting nearly everything. What is shared is tooling, workflow and team skill, not configuration. Providers are…
From lowest to highest: default in the variable block, then TFVAR, then terraform.tfvars, then terraform.tfvars.json, then .auto.tfvars (in lexical order), and highest are -var and -var-file on the CLI. Those two flags share a level: Terraform applies them in command-line order, and the later one…
resource creates and owns a lifecycle; data only reads something that already exists — it never creates, updates or deletes. This is how independent states connect without merging: the platform team owns the VPC, the application team reads it and cannot change it. Two traps:…
init downloads providers and modules into .terraform/, configures the backend, and writes .terraform.lock.hcl. The lock file must be committed. The lock file records exact versions and checksums per provider. Uncommitted, every machine resolves different versions — plans differ between a laptop and CI and the…
From the dependency graph derived from references between resources, not file order. Independent resources are created in parallel. dependson is only for hidden dependencies Terraform cannot see through references: Overusing dependson serializes the graph unnecessarily and slows applies. Prefer real attribute references; reach for dependson…
Locking prevents two concurrent applies on the same state. Without it, two people applying at once overwrite each other's state, leaving orphaned resources tracked by nothing. Production backend checklist: - Encryption at rest — state holds secrets. - Bucket versioning — restore a corrupted state.…
Plan detects the drift during refresh and proposes pulling the resource back to the code, so manual changes are reverted on the next apply. This is both feature and trap: a hotfix opening a port during an incident is silently removed when someone applies an…
No. Modules separate code for reuse, but every module in one configuration shares a single state. A mistyped terraform destroy still takes everything. Two entirely different levels of separation: - Module = code reuse through a variable / output interface. - Separate state = an…
count addresses by index, so removing a middle element shifts every later index and Terraform destroys and recreates in bulk. This is the most expensive trap for newcomers: inserting a subnet mid-list makes the plan recreate 10 EC2 instances. A practical rule: use count only…
Write the matching resource block, import it into state by real ID, then adjust the code until terraform plan reports "No changes". The modern way (Terraform 1.5 and later) declares an import block in code, reviewable in a PR: The -generate-config-out flag only generates configuration…
Declare a moved block. Terraform identifies resources by their address in the configuration, so an undeclared rename reads as destroy plus create. The older way operates on state directly: The moved block is better because it is reviewed in a PR, runs automatically in CI,…
Large projects usually split directories, one state per environment, all calling shared modules. Workspaces suit short-lived temporary environments. Why directories win in production: - Differences between environments appear in code and can be reviewed. - Backend, IAM role and apply permissions are fully separated. -…
No. It only masks the value in output and logs, showing (sensitive value). State still stores it in plaintext. This is a very common misunderstanding behind many leaks: the team assumes the marking is enough and leaves the state bucket readable company-wide. Better secret handling,…
Automatic plan on pull requests with the output posted as a comment, and apply after merge. Infrastructure changes then follow the same process as code changes. Use Trivy (trivy config) as the security scanner. The older tfsec still runs, but Aqua has moved its development…
Layer several protections, because one is not enough: preventdestroy makes any plan destroying that resource fail instead of running. Its limit: it only guards the Terraform path, so console deletion is unaffected — hence deletionprotection at the AWS layer. A common gap: preventdestroy only works…
Command results are not recorded in state, so Terraform only knows whether the provisioner ran, not what configuration the machine is in. A command failing midway leaves the resource tainted. Replace it, in order of preference: 1. A prebuilt AMI via Packer — Terraform only…
Declare several provider blocks with alias, then set provider per resource. Common cases: CloudFront certificates, DR in a second region, and multi-account setups (one account per environment via assumerole). When passing into a module, the module must declare which providers it needs: Letting a module…
With fmt, validate and an automated plan in CI. These three are cheap, run in seconds, and catch most errors before infrastructure is touched. Layers by increasing investment: tfsec used to be the usual scanner here, but it has been folded into Trivy and is…
Only the CI role. Humans have read-only access in production. Every change then passes review, leaves an audit trail, and nobody applies from a laptop. Use OIDC so CI assumes a short-lived role instead of holding access keys: A break-glass path must exist: temporary elevation…
createbeforedestroy. By default Terraform destroys first and creates after, leaving a window with nothing serving. The precondition: both copies must coexist. Many resources enforce unique names, so use nameprefix instead of name or creating the new one fails on a clash. For stateful resources such…
Blocking non-compliant configuration inside the pipeline: public S3 buckets, security groups opening port 22 to 0.0.0.0/0, resources missing required tags. This is Rego v1 syntax, the default since OPA 1.0 and in recent Conftest releases. Older policies written as deny[msg] { no longer parse; rewrite…
One state holding all company infrastructure causes three problems: - A wide blast radius — one mistake in a plan or apply touches everything in the state. - Slowness — every run refreshes every resource in the state. - State locking — only one writer…
Cost becomes visible at PR review time instead of at month end. Three concrete benefits: 1. Estimates before merge — a reviewer immediately sees a PR adding $800 a month. 2. Feasible cleanup — every resource is in code and tagged, so finding what nobody…
Tags enable cost allocation by team and project and answer who owns an unfamiliar resource. Without them the bill is a single number. Apply them once at the provider level: The ManagedBy tag is the most useful during cleanups: it immediately separates Terraform-managed resources from…
Resources already created are recorded in state, so rerunning continues from where it stopped. Terraform has no multi-resource transaction, so there is no full rollback. The more awkward case: the resource was created at AWS but the response was lost, so state never recorded it.…
Reference it by a pinned version, never main. Pointing at main means infrastructure changes because someone merged a PR, and during an incident nobody can trace the cause. A release process needs: clear semver, a changelog per release (especially breaking changes), and real provisioning tests…
Every resource must be named per branch or PR to avoid clashes, and must destroy cleanly when the PR closes. Common friction points: - Globally unique names (S3 buckets, domains, ECR repos). - Resources carrying preventdestroy or deletionprotection copied from production. - Indirect leftovers destroy…