CrackOps
Interview PrepTracksLinuxAWS LabSoonInterview RoomSoon
Sign inStart free
CrackOps

Interview prep for the people who keep production up.

[email protected]
ProductInterview PrepTracksDashboardInterview Room
RolesDevOpsSREPlatformCloud
CompanyAboutContactPrivacyTerms
© CrackOps
Linux / IaC & Config Management / terraform state

terraform state

Inspect and repair Terraform's state

Advancedterraformstaterefactoring

terraform state lets you look inside the state file (list, show, pull) and change how code maps to real objects without touching them (mv, rm, plus import). It's how you rename resources, split code into modules, adopt existing infrastructure, or stop managing something.

Syntaxterraform state (list [ADDR] | show ADDR | mv SRC DST | rm ADDR | pull | push FILE | replace-provider) [-dry-run] · terraform import ADDR ID

Watch it run

You've inherited a repo and want to know what this state tracks and what Terraform recorded for one resource.

devops@devops-lab: ~/infra/envs/dev — zsh — 96×28
➜ ~/infra/envs/dev
Step 1 of 3
terraform state list

One line per resource instance. [0] and [1] come from count; ["a"] from for_each; module.network. prefixes resources created inside a module. These addresses are what every other state command takes.

Anatomy of a command

$
commandterraform

The Terraform CLI.

How it works

State is a JSON document (format version 4) holding, for every resource instance, its address (module path, type, name, count index or for_each key), the provider that manages it, its real ID and all attributes as last seen, plus outputs, a serial number and a lineage ID. It's how Terraform knows that aws_instance.web is i-0a1b2c3d4e5f67890. state list and show read it; pull prints the raw JSON. mv, rm and push modify it: Terraform takes the state lock, writes a new version with serial+1 (and, for a local backend, a .backup file) and releases the lock. They never change the real resources. rm makes Terraform forget an object (it keeps existing in AWS); import, or an import block, does the reverse, asking the provider to read an existing object by ID and adding it to state. Modern code prefers moved, removed and import blocks, which do the same through a normal reviewed plan. State contains secrets in plain text, so the backend must be encrypted and access-controlled.

Options you'll actually use

list [ADDR]All resource addresses, or those under a prefix
show ADDRAll attributes of one resource instance
mv SRC DSTChange an object's address (rename, into a module)
rm ADDRForget an object; it keeps running in the cloud
pull / pushPrint the raw state JSON / overwrite remote state (dangerous)
-dry-runFor mv and rm: show what would happen
import ADDR IDAdopt an existing object (or use an import block)
list -id=IDFind which address holds a given real ID
replace-providerPoint resources at a different provider source

Common mistakes

Editing terraform.tfstate by hand or with sed

One bad edit corrupts IDs or dependencies, and with a remote backend you also bypass locking and serial checks.

Use state mv / rm / import, or moved / removed / import blocks
terraform state rm to 'fix' a resource Terraform keeps trying to change

It stops managing the object, but the block is still in code, so the next plan creates a duplicate.

Fix the code (or ignore_changes for that attribute); rm only when handing the object to another state
Running state mv on prod without -dry-run or a backup

A wrong destination address makes the next plan destroy and recreate real resources.

terraform state pull > backup.json; state mv -dry-run; state mv; terraform plan shows no changes
Committing terraform.tfstate to Git

It contains passwords, keys and private IPs in plain text, and Git merges of state break it.

Remote encrypted backend (S3 with encryption, versioning and locking)

Interview questions

Practice

Try these on a Linux machine of your own. Each task has a hint and a solution.

  1. 1

    In ~/infra (after apply), list only the resources inside module.network, then show the subnet with for_each key "b" (quote it correctly).

  2. 2

    In ~/infra (after apply), rename aws_security_group.web to aws_security_group.web_sg in state, safely. What does the next plan say, and why?

  3. 3

    State is JSON, and so is a lot of IaC tooling output. In the sandbox, pretty-print and query a JSON file from ~/data with python3 (or jq if present).

Related commands

terraform planPreview what Terraform will changeterraform applyCreate, change or destroy real infrastructureterraform initPrepare a Terraform working directoryaws s3Copy, sync and list files in Amazon S3
Previousterraform applyNextansible
Linux / IaC & Config Management / terraform state

terraform state

Inspect and repair Terraform's state

Advancedterraformstaterefactoring

terraform state lets you look inside the state file (list, show, pull) and change how code maps to real objects without touching them (mv, rm, plus import). It's how you rename resources, split code into modules, adopt existing infrastructure, or stop managing something.

Syntaxterraform state (list [ADDR] | show ADDR | mv SRC DST | rm ADDR | pull | push FILE | replace-provider) [-dry-run] · terraform import ADDR ID

Watch it run

You've inherited a repo and want to know what this state tracks and what Terraform recorded for one resource.

devops@devops-lab: ~/infra/envs/dev — zsh — 96×28
➜ ~/infra/envs/dev
Step 1 of 3
terraform state list

One line per resource instance. [0] and [1] come from count; ["a"] from for_each; module.network. prefixes resources created inside a module. These addresses are what every other state command takes.

Anatomy of a command

$
commandterraform

The Terraform CLI.

How it works

State is a JSON document (format version 4) holding, for every resource instance, its address (module path, type, name, count index or for_each key), the provider that manages it, its real ID and all attributes as last seen, plus outputs, a serial number and a lineage ID. It's how Terraform knows that aws_instance.web is i-0a1b2c3d4e5f67890. state list and show read it; pull prints the raw JSON. mv, rm and push modify it: Terraform takes the state lock, writes a new version with serial+1 (and, for a local backend, a .backup file) and releases the lock. They never change the real resources. rm makes Terraform forget an object (it keeps existing in AWS); import, or an import block, does the reverse, asking the provider to read an existing object by ID and adding it to state. Modern code prefers moved, removed and import blocks, which do the same through a normal reviewed plan. State contains secrets in plain text, so the backend must be encrypted and access-controlled.

Options you'll actually use

list [ADDR]All resource addresses, or those under a prefix
show ADDRAll attributes of one resource instance
mv SRC DSTChange an object's address (rename, into a module)
rm ADDRForget an object; it keeps running in the cloud
pull / pushPrint the raw state JSON / overwrite remote state (dangerous)
-dry-runFor mv and rm: show what would happen
import ADDR IDAdopt an existing object (or use an import block)
list -id=IDFind which address holds a given real ID
replace-providerPoint resources at a different provider source

Common mistakes

Editing terraform.tfstate by hand or with sed

One bad edit corrupts IDs or dependencies, and with a remote backend you also bypass locking and serial checks.

Use state mv / rm / import, or moved / removed / import blocks
terraform state rm to 'fix' a resource Terraform keeps trying to change

It stops managing the object, but the block is still in code, so the next plan creates a duplicate.

Fix the code (or ignore_changes for that attribute); rm only when handing the object to another state
Running state mv on prod without -dry-run or a backup

A wrong destination address makes the next plan destroy and recreate real resources.

terraform state pull > backup.json; state mv -dry-run; state mv; terraform plan shows no changes
Committing terraform.tfstate to Git

It contains passwords, keys and private IPs in plain text, and Git merges of state break it.

Remote encrypted backend (S3 with encryption, versioning and locking)

Interview questions

Practice

Try these on a Linux machine of your own. Each task has a hint and a solution.

  1. 1

    In ~/infra (after apply), list only the resources inside module.network, then show the subnet with for_each key "b" (quote it correctly).

  2. 2

    In ~/infra (after apply), rename aws_security_group.web to aws_security_group.web_sg in state, safely. What does the next plan say, and why?

  3. 3

    State is JSON, and so is a lot of IaC tooling output. In the sandbox, pretty-print and query a JSON file from ~/data with python3 (or jq if present).

Related commands

terraform planPreview what Terraform will changeterraform applyCreate, change or destroy real infrastructureterraform initPrepare a Terraform working directoryaws s3Copy, sync and list files in Amazon S3
Previousterraform applyNextansible