Terraform State Interview Questions (tf-state)
Reviewed by Mark Dickie · Last updated
5 questions on this page you can answer and see marked on the spot. Go to the first one
Terraform state is a JSON file that records the mapping between your configuration and the real infrastructure resources Terraform manages. For interviews, the highest-value topics are how state enables plan and apply, the trade-offs between local and remote backends, and what happens when state drifts from your cloud provider. You should also be able to explain the terraform state subcommands (mv, rm, list, show), when state locking matters, and why committing .tfstate files to version control is a problem.
What does Terraform use state for?
State lets Terraform know which configuration blocks correspond to which cloud resources. Without it, Terraform would have to query your entire cloud account on every run to figure out what exists. The state file also stores resource dependencies and outputs, so the next terraform plan can compute the minimal diff.
| State concept | What it means | Interview relevance |
|---|---|---|
| Backend | Where state is stored (local file, S3+DynamoDB, GCS, Terraform Cloud) | Remote vs local trade-offs |
| Locking | Prevents concurrent writes to the same state file | S3+DynamoDB, why it matters in teams |
| Workspaces | Isolated state copies for dev/prod separation | When to use workspaces vs directories |
terraform refresh | Updates state to match real-world resource state | Drift detection, why plan calls it |
.tfstate file | The JSON file itself, often containing sensitive values | Why it shouldn't go in Git |
How do you move or remove resources in state?
- Run
terraform state listto find the resource's current address. - Use
terraform state mv <old> <new>to rename the address; Terraform updates state without touching the real resource. - Run
terraform planto confirm the move shows zero changes. - If a resource is gone from the cloud but still in state, use
terraform state rmto drop the stale entry without destroying anything.
What should you know about remote state backends?
Remote backends store state in a shared, durable location so teams can collaborate. The most common AWS pattern pairs an S3 bucket for storage with a DynamoDB table for locking. On GCP, a GCS bucket with object versioning serves the same role. You need to know how to configure backend blocks, how terraform init -reconfigure switches configurations, and how to migrate state when moving between backends.
Key facts
- Tarmac has 33 Terraform interview questions on this topic, 10 of them on this page, at difficulty 1–5 of 5.
- Tarmac tracked 1,687 job postings asking for Terraform in September 2026.
- Roles asking for Terraform advertise a median base salary of £80,000, across 613 job postings as of September 2026.
- Tarmac last reviewed these Terraform interview questions on 12 October 2026.
At a glance
| Questions | 10 shown · 33 in the bank |
|---|---|
| Difficulty | 1–5 of 5 |
| Formats | Multiple choice, Short answer, True / false, Fill in the blank, Multiple answer, Design exercise |
What you'll review
- drift
- remote state
- state file
Practice questions
Try one before you open the answer. Pick an option and press Check; it's marked on the spot.
In Terraform, what does it mean when a practitioner says the infrastructure has "drifted"?#
Options
Show answer
Drift means the real-world infrastructure no longer matches what Terraform's state file records. It usually happens when someone changes cloud resources outside of Terraform — for example, through the cloud console or CLI — so terraform plan shows unexpected differences even though the .tf files haven't changed. Running terraform plan is the standard way to detect it.
Drift in Terraform refers to a mismatch between the actual state of real-world resources and the state recorded in the Terraform state file. This typically happens when someone makes manual changes (via the cloud console, CLI, or another tool) outside of Terraform. Running terraform plan detects this drift because it compares the state file against live infrastructure. An unapplied configuration change describes an unapplied configuration change, not drift; a lost state file describes a lost state file; a version mismatch is a version mismatch, unrelated to drift.
What is a core benefit of storing Terraform state in a remote backend (such as S3, GCS, or Terraform Cloud) instead of a local terraform.tfstate file?#
Show answer
A remote backend lets every team member share the same state file, so everyone works from one consistent view of the infrastructure. Many remote backends also support state locking, which helps prevent two people from applying changes at the same time.
A remote backend stores the state file in a shared location that all team members and CI pipelines can read and write, so they all see the same record of what Terraform manages. A local state file exists only on one machine, which leads to divergent copies and conflicting changes. Many remote backends also provide locking, which is a further benefit of the same setup.
True or false: storing Terraform state in a remote backend lets multiple team members share a single state file, and the backend can lock state during writes to prevent concurrent modifications.#
Options
Show answer
True. A remote Terraform backend stores state in a shared location so a whole team works from one state file. Backends that support locking hold a lock during writes, so two concurrent runs cannot modify the state at the same time and corrupt it.
A remote backend keeps the state file in a shared, centralized location (for example an S3 bucket or an Azure Storage account), so every team member reads and writes the same state. Backends that support locking acquire a lock before a write, so two concurrent Terraform runs cannot modify the state at the same time. Both halves of the statement are true, so the answer is true.
Most Terraform remote state backends support _____, which prevents two Terraform operations from writing to the same state file at the same time.#
Show answer
Most Terraform remote state backends support state locking, which prevents two Terraform operations from writing to the same state file at the same time.
The mechanism is state locking. Before a Terraform operation that modifies state begins, the backend acquires a lock; if another process already holds the lock, the run waits or fails. This prevents concurrent writes that could corrupt the state file or cause race conditions between team members.
What is the primary purpose of the Terraform state file (terraform.tfstate)?#
Options
Show answer
The state file maps each resource address in your configuration to the real infrastructure object Terraform created (an instance id, a bucket ARN). Terraform reads it to compute the diff between desired and actual state, so it knows what to create, update, or destroy. It is not where you declare desired infrastructure (that's your .tf files), and it is not a credential or plugin cache.
State is Terraform's record of which real object (an AWS instance id, a bucket ARN) corresponds to each resource address in your config. Without it Terraform couldn't tell what already exists, so it couldn't compute a diff or know what to update or destroy. Credentials are supplied by the provider config/environment, the desired state is your .tf files, and plugins are cached under .terraform/. Losing or corrupting state is what makes Terraform try to recreate or orphan live infrastructure.
True or false: storing Terraform state files in a version control system such as Git is considered an anti-pattern, because state files can contain sensitive data and version control systems provide no built-in state locking to prevent concurrent modifications.#
Options
Show answer
Storing Terraform state in Git or another version control system is an anti-pattern. State files can hold secrets like passwords and access keys, and version control offers no state locking, so concurrent applies can corrupt state. Remote backends such as S3 with DynamoDB or Terraform Cloud avoid both problems.
True. The Terraform documentation recommends against storing state in version control. State files can contain sensitive values such as passwords, tokens, and access keys, which should not be exposed in a repository. Version control also has no built-in state locking, so two people running terraform apply at the same time could corrupt the state. Remote backends such as S3 with DynamoDB locking, Azure Blob Storage, GCS, or Terraform Cloud address both problems.
In Terraform v1.x, the S3 backend is configured with a backend "s3" block inside the terraform block. Which of the following arguments are marked Required in the S3 backend schema, meaning they must be set explicitly and cannot be sourced from environment variables or defaults? Select all that apply.#
Options
Pick every one that applies.
Show answer
In Terraform v1.x, the S3 backend marks only bucket and key as Required. region can come from environment variables or provider defaults, and dynamodb_table only enables state locking, so both are Optional. workspace_key_prefix has a default value and is also Optional.
In the current Terraform S3 backend documentation (v1.x), only the bucket name and the object path for the state file are marked Required. The bucket argument names the S3 bucket and the key argument sets the path of the state file inside it. The region can be resolved from the AWS_DEFAULT_REGION or AWS_REGION environment variables or other provider defaults, so it is Optional. The DynamoDB table only enables state locking and is Optional. The workspace key prefix has a default value (env:) and is also Optional.
Your team currently keeps terraform.tfstate on each engineer's laptop. Explain why you'd move to a remote backend (e.g. S3, Terraform Cloud) and what two problems it solves for a team.#
Show answer
A local state file means each engineer has their own copy, so the state diverges and is never authoritative; it also isn't backed up and can be lost or committed to git with secrets in it. A remote backend stores a single shared state in a central, durable location so the whole team plans and applies against the same source of truth. Crucially it enables state locking: while one apply holds the lock, others are blocked, preventing two people from writing state at once and corrupting it. It also gives durability/versioning (S3 versioning, backups) and keeps the (plaintext) state off laptops behind access controls and encryption at rest.
The two big wins are a single shared source of truth (no divergent laptop copies) and state locking to prevent concurrent applies from corrupting state. Strong answers also mention durability/versioning and that state holds secrets in plaintext, so a remote backend with encryption and access control is a security improvement too. This is the question that separates someone who has run Terraform solo from someone who has run it on a team.
You are the platform lead for an organization migrating from a single monolithic Terraform configuration to a multi-team setup. Five product teams will each own their own Terraform root module, all deploying into shared AWS accounts across three environments (dev, staging, prod). Currently, every team's state file lives on individual developer machines. Design a complete Terraform state management strategy that addresses: (1) remote state storage and backend configuration, (2) state isolation between teams and between environments, (3) state locking and concurrency control, and (4) the recovery workflow for a corrupted or manually-edited state file.#
Show answer
We would migrate all state to an S3 backend (one bucket per AWS account or a single bucket with KMS encryption and a strict key prefix scheme) fronted by a DynamoDB table for locking. Each team-environment pair gets its own state key path: for example s3://tf-state-prod/team-a/prod/terraform.tfstate. This gives us per-team, per-environment isolation at the object level.
For environment isolation we deliberately choose separate backend keys over Terraform Workspaces. Workspaces share a single backend configuration and make it trivial to accidentally run terraform apply against the wrong environment — the workspace is just a CLI flag. Separate keys let us enforce isolation through IAM: each team's CI role gets s3:GetObject/s3:PutObject and DynamoDB lock permissions only on its own key prefix and lock-table partition. A team-A role literally cannot read team-B's state object.
Locking is handled by the DynamoDB lock table. On every plan and apply, Terraform writes a lock item keyed by the S3 state path; if the item already exists, the run aborts with the lock ID. If a pipeline crashes without releasing the lock, the operator verifies (via CI logs and a DynamoDB DescribeTable check on lock age) that no run is genuinely in progress, then runs terraform force-unlock <lock-id> to remove the stale item.
For state recovery we enable S3 bucket versioning. If a state file is corrupted or manually edited, we identify the last known-good version via the S3 version list, download it locally, and run terraform state push -force good-state.tfstate. The -force flag is required because the good version has a lower serial than the current (corrupted) state; Terraform's serial check exists precisely to prevent silent state rollbacks, so we must acknowledge the override. All S3 and DynamoDB operations are captured in CloudTrail and S3 access logs, giving us an audit trail of who pushed the replacement state and when. As a post-incident step, we run terraform plan to confirm the restored state matches reality and investigate how the corruption occurred.
This design exercise tests senior-level understanding of Terraform state internals: backend configuration choices, the serial field's role in state integrity, locking via DynamoDB, IAM-level isolation, and the recovery workflow using S3 versioning and terraform state push -force. A strong answer must address all four rubric criteria concretely with AWS-native primitives.
You are the platform engineering lead at a company with 50+ engineering teams. Each team manages its own Terraform configurations across three environments (dev, staging, prod) in AWS. Currently, every team stores state in a single shared S3 bucket with a DynamoDB lock table, using workspace names for isolation (e.g. team-payment-dev, team-payment-prod). A recent incident occurred where Team A's terraform apply overwrote Team B's state because both teams were accidentally configured with the same state key. The platform team owns the backend infrastructure and must enforce guardrails.#
Show answer
State Isolation
We replace the single shared S3 bucket + workspace-based isolation with a dedicated S3 bucket per team (e.g. tfstate-payment, tfstate-checkout). Within each team bucket, state keys are organized by environment: payment/dev/terraform.tfstate, payment/staging/terraform.tfstate, payment/prod/terraform.tfstate. This eliminates the collision class entirely: a misconfigured workspace name in one team's backend block cannot overwrite another team's state because the teams write to physically separate buckets. Workspaces are insufficient as a team-boundary isolation mechanism because they share the same backend configuration and S3 key prefix — if two teams accidentally use the same workspace name or state key, Terraform happily writes one state over the other with no warning.
Access Control & Encryption
Each team bucket uses SSE-KMS with a per-team KMS CMK (e.g. alias/tfstate-payment). The platform team owns the KMS keys and grants each team's IAM role kms:Decrypt, kms:Encrypt, and kms:GenerateDataKey on only their key. S3 bucket policies restrict s3:GetObject and s3:PutObject to the team's IAM role, scoped to the team's key prefix within the bucket. Since Terraform state is stored as a single S3 object per workspace, IAM policy conditions use the object key path in the resource ARN (e.g. arn:aws:s3:::tfstate-payment/payment/prod/terraform.tfstate) to enforce isolation. The platform team retains kms:CreateKey, kms:ScheduleKeyDeletion, and kms:RotateKey on all keys for centralized rotation. DynamoDB lock tables are either per-team or use a shared table with a per-team hash key namespace, with IAM policies scoped accordingly so that a team cannot acquire or release another team's lock.
Cross-Team State Sharing
Teams that need to consume another team's outputs use a terraform_remote_state data source:
data "terraform_remote_state" "payment" {
backend = "s3"
config = {
bucket = "tfstate-payment"
key = "payment/prod/terraform.tfstate"
region = "us-east-1"
dynamodb_table = "tflock-payment"
}
}
The consuming team's IAM role is granted read-only s3:GetObject on the specific state object and kms:Decrypt on the producing team's KMS key — no write access, no DynamoDB lock-table write access. terraform_remote_state exposes only the outputs block of the state, not raw resource attributes, so the producing team curates which values are shared by defining outputs explicitly. Importantly, the remote-state read does NOT acquire a state lock, so multiple consumers can read concurrently without blocking the producing team's applies.
Policy Enforcement & Audit
- Config-level secret prevention: All CI/CD pipelines run
tfsecorcheckovscans that flag resources with sensitive attributes not markedsensitive = true, andtflintrules that rejectoutputblocks exposing secrets. Additionally, a custom Sentinel policy (for Terraform Enterprise/Cloud users) or OPA policy (for open-source) checks that allvariableandoutputdeclarations handling secrets usesensitive = true. These tools scan HCL configuration, not state file contents — they prevent secrets from leaking through outputs but cannot detect a secret already embedded in a resource attribute in state. - State-content secret scanning: Because config-level tools do not inspect state files, the platform team runs a scheduled job that pulls each team's state object via
terraform state pulland pipes the JSON throughtrufflehogto detect plaintext secrets in resource attributes (e.g., a password hardcoded in a resource argument). If a secret is found, the job alerts the owning team and triggers credential rotation. This complements the config-level prevention above by catching secrets that slip through into state despite config policies. - Backend standards: The platform team publishes a versioned Terraform backend module that teams must use. This module hardcodes encryption settings, key naming conventions, and DynamoDB table configuration. A wrapper script or Makefile enforces
terraform init -backend-config=with only the team-specific values, preventing manual misconfiguration. - Audit logging: AWS CloudTrail data events are enabled on every state bucket, logging every
GetObjectandPutObjectcall with the caller IAM principal, timestamp, and object key. This provides a tamper-resistant audit trail. S3 server access logs are also enabled as a secondary, lower-cost log for long-term retention, but CloudTrail is the primary audit mechanism because it integrates with SIEM tools and captures the IAM principal identity.
Zero-Downtime Migration
Migration is performed team-by-team in a phased rollout:
- Prepare: The platform team creates the new per-team bucket, KMS key, and DynamoDB table for a single pilot team.
- Pull: The team runs
terraform state pullagainst the old shared backend, producing a localterraform.tfstatefile. - Push: The team updates their backend configuration to point at the new bucket and runs
terraform state push terraform.tfstateto write the state to the new backend. - Verify: The team runs
terraform state pullon the new backend and diffs the JSON against the old state. ThelineageUUID must match and theserialmust be equal or higher. The team runsterraform plan— it should show no changes (or only the expected diff from the backend switch). - Cutover: The team's CI/CD pipeline is updated to use the new backend. The old state object in the shared bucket is preserved (not deleted) until all 50+ teams have confirmed migration.
- Rollback: If any step fails, the team reverts their backend config to the old shared bucket — the old state object is untouched and immediately usable. No state loss occurs because
state pushto the new backend is additive; it does not delete from the old backend.
This process is repeated for each team, one at a time, with the platform team monitoring CloudTrail for any unexpected state access patterns during the migration window.
This is a staff-level design question because it requires synthesizing Terraform state internals (lineage/serial verification, terraform_remote_state lock-free reads, output-only exposure), AWS security primitives (SSE-KMS with per-team CMKs, IAM conditions on S3 object keys, CloudTrail data events), policy-as-code tooling (Sentinel/OPA/tfsec), state-content secret scanning (trufflehog), and a phased zero-downtime migration strategy — all at organizational scale with 50+ teams. The rubric criteria were corrected so that: (1) c1 and c2 no longer double-credit the IAM-prefix isolation explanation — c1 owns the isolation architecture and workspace-insufficiency argument, while c2 focuses on encryption, IAM scoping, and DynamoDB lock table isolation as a distinct concern; and (2) c4's enforcement mechanisms are split into config-level prevention (tfsec/checkov enforcing sensitive = true) and state-content scanning (trufflehog/gitleaks/Macie pulling state files), so the rubric no longer conflates scanning HCL config with scanning state file contents.
Related interview questions
Job market
See terraform salaries and hiring demand from live job postings.
The other 23 questions
This page shows 10 and marks what you pick. That's as far as a page can go. A free account opens the other 23 and keeps every answer. What you miss comes back until it's right: after a day, then at longer gaps.
Free · the whole bank · 100 marked answers per 30 days · written feedback on the paid plan