FlashGenius Logo FlashGenius
Terraform Associate 004 · Page 4 of 5

State Management & Infrastructure Maintenance

Terraform Associate 004 · Objectives 6 & 7

Backends · State Locking · Remote State · Drift · moved · removed · Import · state CLI · TF_LOG

Study with Practice Tests →

Objectives 6 & 7 — What the Exam Tests

Objectives 6 and 7 together cover the full lifecycle of Terraform state — how it's stored, protected, synchronized, and inspected — plus hands-on infrastructure maintenance skills like importing existing resources and debugging with verbose logging. Objective 6 dives into local vs. remote backends, state locking (including DynamoDB integration for S3), detecting and resolving configuration drift with -refresh-only, and state manipulation commands. Objective 7 covers importing pre-existing infrastructure (both the modern import block and the legacy CLI command), state inspection commands, and the TF_LOG family of environment variables. Together these objectives represent heavily tested, practical day-to-day Terraform skills.

Local Backend Remote State S3 Backend DynamoDB Locking State Locking terraform init -refresh-only moved block removed block state mv / rm import block terraform import TF_LOG force-unlock

Core Concepts at a Glance

Six foundational pillars of state management and infrastructure maintenance

🗃️

Local vs. Remote Backends

The local backend writes terraform.tfstate to disk — simple but unsuitable for teams. Remote backends (S3, GCS, AzureRM, HCP Terraform) store state centrally, enable team collaboration, and support encryption and versioning.

🔒

State Locking

Terraform acquires a lock before any operation that modifies state (apply, destroy) to prevent concurrent corruption. S3 uses a DynamoDB table; HCP Terraform has built-in locking. The local backend does NOT lock by default.

🔄

Drift Detection & Refresh

Drift occurs when real infrastructure diverges from Terraform state due to out-of-band changes. terraform plan reveals drift. terraform apply -refresh-only updates state to match reality without altering infrastructure.

📦

moved & removed Blocks

The moved block renames/moves a resource in state without destroy-and-recreate. The removed block (Terraform 1.7+) removes a resource from state management without destroying it in the cloud provider.

📥

Importing Existing Infrastructure

The import block (Terraform 1.5+) is the recommended approach — it can generate config with -generate-config-out. The legacy terraform import CLI command requires you to manually write the resource block first.

🐛

Verbose Logging with TF_LOG

Set TF_LOG to TRACE, DEBUG, INFO, WARN, or ERROR to control log verbosity. Combine with TF_LOG_PATH to write logs to a file. Crash logs are auto-saved to crash.log.

Objectives 6 & 7 Quick Reference

Objective Sub-Objective Key Commands / Concepts
6a Local backend terraform.tfstate, terraform.tfstate.backup, no locking, .gitignore
6b State locking DynamoDB for S3, terraform force-unlock, automatic on apply/destroy
6c Remote backends backend "s3" block, -reconfigure, -migrate-state, partial config
6d Drift & state ops -refresh-only, moved, removed, state list/show/mv/rm
7a Import infra import {} block, terraform import CLI, -generate-config-out
7b Inspect state state list/show/pull/push, terraform show
7c Verbose logging TF_LOG, TF_LOG_PATH, TF_LOG_CORE, TF_LOG_PROVIDER, crash.log

Deep Dive — Objectives 6 & 7

Detailed coverage of all exam sub-objectives with syntax, nuance, and edge cases

Objective 6a — Local Backend

Default State Storage

When no backend block is configured, Terraform defaults to the local backend. State is written to terraform.tfstate in the working directory. A backup copy (terraform.tfstate.backup) is created before each state update so you can recover from a failed apply.

  • State file is plain JSON — contains resource attributes, including secrets
  • No built-in locking — two concurrent applies can corrupt state
  • Not practical for teams — each developer has their own local copy
  • Always .gitignore state files: they contain sensitive data (passwords, private keys)
  • Suitable for learning and solo development only

Objective 6b — State Locking

Why Locking Matters

Without locking, two engineers running terraform apply simultaneously can interleave writes and corrupt the state file. Terraform automatically acquires a lock before any operation that modifies state: apply, destroy, state mv, and others.

  • Local backend: does NOT lock by default
  • S3 backend: requires a DynamoDB table — add dynamodb_table = "terraform-locks" to the backend block
  • HCP Terraform / Terraform Cloud: built-in locking, no extra config needed
  • GCS, AzureRM: native locking support via blob leases / GCS locks
  • Not all backends support locking — check provider docs

force-unlock

If Terraform crashes mid-apply, it may leave a stale lock. Use terraform force-unlock <lock-id> to manually release it. The lock ID is displayed in the error message when a lock cannot be acquired.

  • Use with caution — only release a lock when you are certain no other process holds it
  • The lock ID is a UUID generated at lock acquisition time
  • Running force-unlock on an active lock can corrupt state

Objective 6c — Remote State with Backend Block

S3 Backend Configuration

The most common remote backend on the exam. The backend block lives inside the terraform {} block:

terraform {
  backend "s3" {
    bucket         = "my-tf-state"
    key            = "prod/terraform.tfstate"
    region         = "us-east-1"
    dynamodb_table = "terraform-locks"
    encrypt        = true
  }
}
  • bucket: S3 bucket name (must exist before init)
  • key: path within bucket (use workspace-aware paths in multi-env setups)
  • dynamodb_table: enables state locking via DynamoDB
  • encrypt = true: enables server-side encryption of state

Common Backends

BackendUse CaseLocking
s3AWS teamsDynamoDB table
azurermAzure teamsBlob lease
gcsGCP teamsGCS object lock
httpCustom REST APIOptional (via API)
kubernetesK8s secret storageLease-based
consulHashiCorp stackConsul locks

Init Flags for Backend Changes

  • terraform init -reconfigure: re-initializes the backend without migrating state; use when you change backend config but DON'T want to migrate existing state
  • terraform init -migrate-state: migrates state from the old backend to the new backend configuration
  • Partial configuration: sensitive values (credentials, tokens) can be omitted from the backend block and supplied via -backend-config="key=value" CLI flags or env vars at init time — keeps secrets out of VCS

Objective 6d — Resource Drift & State Management

Detecting and Resolving Drift

Drift occurs when someone manually changes infrastructure outside of Terraform (e.g., resizing an instance in the AWS console). Terraform state no longer matches reality.

  • terraform plan: highlights drift as differences between state and provider-reported attributes
  • terraform apply -refresh-only: updates state to match real infrastructure WITHOUT making any infrastructure changes — replaces the deprecated terraform refresh command
  • terraform refresh: deprecated in Terraform 1.x; always prefer -refresh-only flag

The moved Block

When you rename a resource in your config, Terraform would normally destroy the old one and create a new one. The moved block records the rename so Terraform updates state without recreating the resource:

moved {
  from = aws_instance.old_name
  to   = aws_instance.new_name
}
  • Works for module moves too: from = aws_instance.footo = module.web.aws_instance.foo
  • Can be committed and then removed in a follow-up PR once all state is updated
  • Does NOT destroy or recreate the resource

The removed Block (Terraform 1.7+)

Removes a resource from Terraform state management without destroying the actual cloud resource:

removed {
  from = aws_instance.example
  lifecycle {
    destroy = false
  }
}
  • destroy = false: Terraform stops tracking the resource but leaves it running
  • destroy = true (default if omitted): destroys the resource and removes from state
  • Useful when handing off a resource to another team's Terraform config

State CLI Commands

CommandPurposeDestructive?
terraform state listList all tracked resourcesNo
terraform state show <addr>Show all attributes of one resourceNo
terraform state mv <src> <dst>Rename/move resource in stateModifies state
terraform state rm <addr>Remove from state (does NOT destroy)Modifies state
terraform state pullDownload and print state JSON to stdoutNo
terraform state push <file>Upload local state file to remote (dangerous)Overwrites remote

Key distinction: terraform state rm stops Terraform from managing a resource — it does NOT call the provider's destroy API. The resource keeps running. To actually delete the resource, use terraform destroy.

Objective 7a — Importing Existing Infrastructure

Modern: import Block (Terraform 1.5+)

The recommended approach. Declare an import block in your config:

import {
  to = aws_instance.example
  id = "i-1234567890abcdef0"
}
  • Run terraform plan to preview the import, then terraform apply to execute
  • Add -generate-config-out=generated.tf to terraform plan — Terraform auto-generates the resource block (experimental but useful)
  • After applying, remove the import block — it's a one-time operation
  • Import ID format varies by resource type — always check the provider documentation

Legacy: terraform import CLI Command

terraform import aws_instance.example i-1234567890abcdef0
  • Requires writing the resource block in config before running the command
  • Does NOT auto-generate config — you must manually write all attributes
  • Imports directly into state; subsequent plan may show drift if config is incomplete
  • Still valid and supported but the import block approach is preferred

Objective 7b — CLI to Inspect State

State Inspection Commands

  • terraform state list: lists all resource addresses tracked in state; use -id=<real-resource-id> to filter by actual provider resource ID
  • terraform state show <address>: prints all attributes of a single resource in human-readable form
  • terraform state pull: downloads and prints the current state as raw JSON to stdout — useful for scripting or manual inspection
  • terraform state push <file>: manually uploads a state file to the remote backend — overwrites remote state, use with extreme caution
  • terraform show: shows the current state (or a saved plan) in human-readable form
  • terraform show terraform.tfplan: shows the contents of a saved plan file

Objective 7c — Verbose Logging

TF_LOG Environment Variable

Set TF_LOG before running any Terraform command to enable detailed logging output to stderr:

LevelVerbosityUse When
TRACEMost verboseDeep debugging — HTTP requests, gRPC calls, provider plugin communication
DEBUGVerboseStep-by-step execution flow, variable resolution
INFOInformationalGeneral operational messages
WARNWarnings onlyNon-fatal issues you should know about
ERRORLeast verboseFatal errors only
  • TF_LOG=TRACE terraform apply — maximum logging to stderr
  • TF_LOG_PATH=/tmp/terraform.log — redirects logs to a file (in addition to or instead of stderr)
  • TF_LOG_CORE — sets log level for Terraform core separately
  • TF_LOG_PROVIDER — sets log level for provider plugins separately
  • TF_LOG="" — disables logging entirely
  • crash.log: auto-generated in the working directory on a Terraform panic — always include when filing bug reports with HashiCorp

Memory Hooks

Six sticky mental models to anchor state management concepts for exam day

🏠

Backend Basics

"Local backend = solo only; remote = team play"

The local backend stores state on your laptop — no locking, no sharing. The moment a second person joins the project, move to a remote backend. Think of local as a single-player save file and remote as a shared cloud save.

🔑

S3 + DynamoDB

"DynamoDB = the lock keeper for S3 backend"

S3 stores the state file; DynamoDB stores the lock record. Without DynamoDB, the S3 backend has no locking. Remember: one service stores the state, a separate service guards access to it.

📝

moved vs. removed

"`moved` = rename in state; `removed` = forget without destroy"

moved tells Terraform "this resource is now called something else — don't recreate it." removed tells Terraform "stop tracking this — but leave it running." Two very different state surgery operations.

📊

Log Level Order

"TF_LOG levels: TRACE > DEBUG > INFO > WARN > ERROR (most → least)"

Remember the order: T-D-I-W-E from noisiest to quietest. Use a mnemonic: "Totally Detailed, I Want Everything". TRACE floods your terminal; ERROR only shows fatal issues.

🔄

Refresh-Only Mode

"`-refresh-only` = sync state to reality (no infra changes)"

-refresh-only is a read-only pass — it queries providers and updates your state file to match what actually exists, without touching any real infrastructure. It replaced the deprecated terraform refresh command.

📥

Import Methods

"import block generates config; CLI import requires you write it first"

The modern import block can auto-generate resource config with -generate-config-out. The legacy terraform import CLI demands you write the resource block manually before it will add state. New approach = more automation.

Practice Quiz

10 questions · Objectives 6 & 7 · Click an answer to check

Score: 0 / 0
Question 1 of 10
Which AWS service is used to provide state locking when using the S3 backend in Terraform?
Question 2 of 10
A team member manually resized an EC2 instance in the AWS console without updating Terraform config. Which command updates Terraform state to reflect the real infrastructure WITHOUT making any infrastructure changes?
Question 3 of 10
You rename an AWS instance resource from aws_instance.web to aws_instance.webserver in your config. Which approach prevents Terraform from destroying and recreating the resource?
Question 4 of 10
Which TF_LOG level produces the MOST verbose output, including HTTP request/response details and provider plugin gRPC communication?
Question 5 of 10
A developer runs terraform state rm aws_s3_bucket.logs. What is the result?
Question 6 of 10
Which Terraform CLI flag, added to terraform plan, causes Terraform to automatically generate HCL configuration for resources being imported using an import block?
Question 7 of 10
You changed the backend configuration from S3 to GCS and want to migrate the existing state to the new backend. Which terraform init flag should you use?
Question 8 of 10
Which of the following is a limitation of the local Terraform backend that makes it unsuitable for team environments?
Question 9 of 10
Terraform crashed mid-apply and left a stale lock on the S3 backend. You have confirmed no other process is running. Which command releases the lock?
Question 10 of 10
What is the key difference between terraform state show and terraform state list?

Flashcards

Click a card to flip it and reveal the answer. 8 cards covering state management and infrastructure maintenance.

State Locking
Why does Terraform use state locking, and when is it automatically acquired?
State locking prevents concurrent modifications that could corrupt the state file. Terraform automatically acquires a lock before any operation that writes to state: apply, destroy, and state mv. Read-only commands (plan, show) do not require a lock.
Objective 6b
S3 + DynamoDB Backend
What are the two key backend block attributes that enable locking and encryption for the S3 backend?
dynamodb_table = "terraform-locks" enables state locking via DynamoDB (prevents concurrent applies). encrypt = true enables server-side encryption of the state file at rest in S3. Both are strongly recommended for production use.
Objective 6c
moved Block
Write the moved block syntax to rename aws_instance.old to aws_instance.new without destroying the resource.
moved {
from = aws_instance.old
to = aws_instance.new
}

Terraform updates the state entry to the new address without calling destroy or create on the provider.
Objective 6d
removed Block
What does the removed block with lifecycle { destroy = false } do to a resource?
The removed block (Terraform 1.7+) removes the resource from Terraform state management. With destroy = false, the actual cloud resource continues to exist and run — Terraform simply stops tracking it. Useful for handing resources off to another config.
Objective 6d
TF_LOG Levels
List the TF_LOG levels from most verbose to least verbose.
TRACE (most) → DEBUGINFOWARNERROR (least)

TRACE: HTTP calls, gRPC, plugin details. DEBUG: execution flow. INFO: general ops. WARN: non-fatal. ERROR: fatals only. Set TF_LOG="" to disable.
Objective 7c
Refresh-Only vs. Refresh
What is the difference between terraform apply -refresh-only and terraform refresh?
terraform apply -refresh-only: the current recommended command. Updates state to match real infrastructure, shows you a plan, requires approval — no infra changes made.

terraform refresh: deprecated in Terraform 1.x. Updated state without a plan step. Always prefer -refresh-only.
Objective 6d
terraform state rm
What happens to the actual cloud resource when you run terraform state rm?
Nothing happens to the real infrastructure. terraform state rm only removes the resource entry from the Terraform state file — it does NOT call any provider destroy API. The resource continues to exist in the cloud provider, but Terraform stops managing it.
Objective 6d / 7b
Import Block vs. CLI Import
What is the main advantage of the import block (Terraform 1.5+) over the legacy terraform import CLI command?
The import block can auto-generate HCL resource configuration using -generate-config-out=file.tf during terraform plan — you don't need to write config manually.

The legacy terraform import CLI requires you to write the full resource block before running the import. No config generation is possible.
Objective 7a

Study Advisor

Select a topic area to get targeted study tips and exam focus points

Objective 6a & 6c

🗃️ State Backends — Exam Focus

  • Know that the local backend is the default — no backend block needed, state goes to terraform.tfstate
  • Memorize the S3 backend block attributes: bucket, key, region, dynamodb_table, encrypt
  • Understand partial configuration: omit credentials from the backend block and supply via -backend-config flags or environment variables at init time
  • Know the difference between -reconfigure (re-init, no migration) and -migrate-state (re-init + move state)
  • Common backends to recognize: s3, azurerm, gcs, http, kubernetes, consul
  • The cloud block is the alternative to backend for HCP Terraform — covered in Page 5
  • Always .gitignore state files — they contain sensitive values like passwords and private keys
Objective 6b

🔒 State Locking — Exam Focus

  • Locking is automatic for write operations (apply, destroy) — you don't have to do anything to enable it once the backend supports it
  • The local backend does NOT lock — this is a key exam distractor
  • S3 locking requires a separate DynamoDB table — the table name goes in dynamodb_table = "..." inside the backend block
  • HCP Terraform has built-in locking — no DynamoDB or extra config needed
  • The command to release a stuck lock is terraform force-unlock <lock-id>
  • The lock ID appears in the error message when Terraform cannot acquire the lock
  • Only use force-unlock when you are absolutely certain no other process is holding the lock
Objective 6d

🔄 Drift & Refresh — Exam Focus

  • Drift = real infra differs from Terraform state due to out-of-band changes
  • terraform plan detects drift — shows what would change if you applied
  • terraform apply -refresh-only = sync state to reality, NO infra changes — always prefer this
  • terraform refresh is deprecated in Terraform 1.x — know it exists but prefer -refresh-only
  • The moved block prevents destroy-and-recreate when renaming resources
  • The removed block (1.7+) removes a resource from state management without destroying the real resource
  • Key state commands: state list (all resources), state show <addr> (one resource), state mv (rename), state rm (remove from state, NOT destroy)
Objective 7a & 7b

📥 Importing Resources — Exam Focus

  • Two methods: import block (Terraform 1.5+, recommended) and terraform import CLI (legacy)
  • Import block: declare in config → run terraform plan → run terraform apply
  • Add -generate-config-out=generated.tf to terraform plan to auto-generate HCL config for the imported resource
  • Legacy CLI: you MUST write the resource block in config BEFORE running terraform import <address> <id>
  • Import ID format varies by resource — always check provider documentation (e.g., EC2 uses instance ID, IAM Role uses role name)
  • After successful import, delete the import block from config — it's a one-time operation
  • terraform state pull prints state JSON — useful for scripting; terraform state push overwrites remote state (dangerous)
Objective 7c

🐛 Debugging — Exam Focus

  • TF_LOG levels from most to least verbose: TRACE > DEBUG > INFO > WARN > ERROR
  • TF_LOG=TRACE gives maximum detail including HTTP calls and provider gRPC communication
  • TF_LOG_PATH=/path/to/file.log redirects log output to a file
  • TF_LOG_CORE and TF_LOG_PROVIDER allow separate log levels for Terraform core and provider plugins
  • Set TF_LOG="" to disable logging
  • On a Terraform panic, crash.log is auto-generated in the current working directory
  • Always include crash.log when filing bug reports — it contains the panic stack trace
  • VERBOSE is NOT a valid TF_LOG level — only TRACE, DEBUG, INFO, WARN, ERROR

Resources

Official documentation and study materials for Objectives 6 & 7

Official Docs

Terraform Backends

Complete reference for all supported backends, backend configuration, and partial configuration patterns.

developer.hashicorp.com →
Official Docs

S3 Backend Reference

Detailed S3 backend configuration including DynamoDB locking, encryption, workspace support, and IAM requirements.

developer.hashicorp.com →
Official Docs

State: moved Block

Refactoring resources and modules with the moved block — syntax, examples, and multi-version compatibility notes.

developer.hashicorp.com →
Official Docs

Import Block

Modern import block syntax, generating config with -generate-config-out, and import workflow best practices.

developer.hashicorp.com →
Official Docs

Debugging Terraform (TF_LOG)

Full reference for TF_LOG, TF_LOG_PATH, TF_LOG_CORE, TF_LOG_PROVIDER, and crash log behavior.

developer.hashicorp.com →
Official Docs

State Command Reference

Full reference for terraform state subcommands: list, show, mv, rm, pull, push, and force-unlock.

developer.hashicorp.com →
Exam Guide

Terraform Associate 004 Study Guide

Official HashiCorp exam study guide and objectives list for the Terraform Associate 004 certification.

developer.hashicorp.com →
Practice

FlashGenius Practice Tests

Full-length Terraform Associate 004 practice exams with timed mode, detailed explanations, and performance tracking.

flashgenius.net/register →

Ready to Test Your Knowledge?

Practice with full-length Terraform Associate 004 timed exams and performance analytics on FlashGenius.

Start Studying Free →