State Management

Terraform / Infrastructure as Code

Chapter 5 · State Management

Chapter 4's warn-box left a thread open: state stores real secret values in plaintext. This chapter explains what state actually is, why Terraform can't function without it, and what that means for how it must be handled.

What State Is & Why Terraform Needs It

Every apply writes terraform.tfstate — a JSON file mapping every resource address (local_file.hello) to the real-world object it created and every attribute that object actually has. Without it, Terraform would have no way to distinguish "a resource this configuration already created" from "a resource with the same name that happens to exist for some other reason" — every plan would risk creating duplicates rather than recognizing something as already satisfied. State is the literal record that makes the desired-vs-actual comparison from Chapter 1 possible at all.

Local State

By default, state lives as a plain file on local disk — fine for solo experimentation, but it means only one machine has any record of what Terraform manages. Anyone else running apply against the same configuration, from a different machine, has no shared state to compare against.

Never commit terraform.tfstate to git
State contains the full, real attribute values of every managed resource — including anything marked sensitive in Chapter 4, stored here in plain, unredacted text. Committing it is exactly the same mistake as Chapter 2's hardcoded-credential warning: permanently exposed in git history the moment it's pushed. Add *.tfstate* to .gitignore, the same discipline git1-6 already covers.

Remote State — A Preview

Local state has two problems at once: secrets sitting in a file that's tempting to accidentally commit, and no shared record for a team. Chapter 6 covers remote backends in full — storing state in a shared, access-controlled location instead of on one person's disk, solving both problems together.

terraform state Commands

Inspecting and safely modifying state without hand-editing the file:

$ terraform state list local_file.hello $ terraform state show local_file.hello # local_file.hello: resource "local_file" "hello" { content = "Hello from Terraform!" filename = "./hello.txt" } $ terraform state mv local_file.hello local_file.greeting $ terraform state rm local_file.old_resource

state mv renames a resource in state without destroying and recreating the real object — Terraform otherwise treats a renamed block exactly like Chapter 3's addressing rules imply: a different address means a different resource, and a different resource means destroy-then-create.

Never hand-edit the state file
State's internal structure is easy to corrupt by editing directly — a single malformed field can make Terraform lose track of a resource entirely. Use terraform state mv/rm/list/show instead; they modify state safely, through Terraform's own understanding of its structure.

Drift Detection, In Full

cloud1-11 introduced drift conceptually. Here's the actual mechanism: terraform plan performs a three-way comparison — the desired configuration (the .tf files), the last-known state (what Terraform believes exists), and a fresh refresh against the real infrastructure itself. If a manual console change altered something Terraform manages, the refresh step detects that the real world no longer matches state, and plan reports it — exactly the "manual fix gets silently reverted by the next automated apply" scenario cloud1-11 warned about.

SourceWhat it represents
ConfigurationWhat the .tf files say should exist
StateWhat Terraform last recorded as existing
Real infrastructureWhat's actually running right now, checked via refresh

Automatic Backups

Every state-modifying command writes terraform.tfstate.backup before making its change — a single-generation safety net if a state operation goes wrong.

Hands-On Exercises

Exercise 1

Explain, in your own words, why Terraform needs a state file at all — what specifically would break if it tried to operate without one?

📄 View solution
Exercise 2

Explain the three-way comparison terraform plan performs, and how it's able to detect a manual console change as drift.

📄 View solution
Exercise 3

A teammate wants to rename a resource block from "web" to "app_server" without Terraform destroying and recreating the real infrastructure. What command should they use, and why is hand-editing the state file instead a real risk?

📄 View solution

Chapter 5 Quick Reference

  • State — the record mapping configuration to real-world resources; required for desired-vs-actual comparison
  • Never commit *.tfstate* — plaintext secrets, same risk as a hardcoded credential
  • terraform state list/show/mv/rm — safe ways to inspect and modify state
  • Never hand-edit the state file directly
  • Drift — detected by comparing configuration, state, and a real-infrastructure refresh, three ways