Infrastructure as Code
Advanced 15 min read Infrastructure as Code

State Management

The memory your plans depend on

IaC state is the tool's memory and the source of a plan's 'reality'. Remote backends with locking, backup, and audit are non-negotiable in teams; misuse of state is the top reason infra tools bite.

remote statelockbackendterraform statedriftmigration
Prerequisites: Terraform Concepts
Before we start

What you will learn

  • Explain why state is essential, not incidental
  • Configure remote backends with locking + backup
  • Handle state surgery: import, move, remove, migration
In 60 seconds

Every resource your tool owns has a state entry (attributes, IDs, dependencies). Remote state + locking avoid concurrent applies; backups save you from corruption. 'Where is state?' is the first question of any method review.

Introduction

What is this?

Backend options: local (bad for teams), S3 (AWS; dynamodb lock), GCS (state bucket), Azure blob+Lease; Terraform Cloud remote; OpenTofu remote. Features: consistency (read-before-plane), locking (avoid two applies racing), state versioning (rollback), workspaces (parallel envs on one backend) vs state per directory. Surgical commands: terraform import (adopt existing infra), state mv/rm/pull/push/shallow list; Tainted resources (legacy) vs replace. Drift detection: refresh/plan compares state vs provider's view. Corruption/hand-edits/forks → reinit, recovery from backup, or manual import/reconstruct. Secrets in state (plan outputs, values): encrypt the backend, restrict read access.

Motivation

Why do you need it?

  • Without remote state, two engineers plan against stale snapshots → clobbering applies.
  • Locking is the difference between 'worked earlier' and 'worked in parallel twice'.
  • State unvblocked import/moves mean migrating manual infra to code without rebuild.
  • A corrupted local state file destroyed more infra than any misconfig I've debugged.
Think about it

Mental model

Imagine

A construction logbook shared by all crews, updated and locked nightly

Think of

Remote state

Each crew (engineer) reads the logbook before laying anything (plan) and writes when done (apply); the on-night lock (dynamo lock) keeps two crews from pouring concrete over each other's work.

Mechanics

How it works

  • Every apply writes each resource's final attributes into state.
  • Next plan reads state + queries the provider for living resources.
  • Locking (DynamoDB/consul/GCS object lock) holds during apply, released after.
  • State versioned in the backend (S3 objects history) for rollback to prior versions.
  • Import/move edit the address book so existing resources join the codebase's graph.

State as memory lane.

Apply
Lock
Plan
Diff
Versioned
Hands-on

Examples

A healthy remote backend shape

A healthy remote backend shape
terraform {
backend "s3" {
bucket = "acme-tfstate-prod"
key = "checkout/terraform.tfstate"
region = "us-east-1"
dynamodb_table = "tf-locks"
encrypt = true
}
}
# now: two people run apply → only one wins the lock

Remote, locked, encrypted, versioned: the gold-standard memory for any team touching the same infra.

Real world

In production

  • Per-environment state files (or dirs) in one bucket, keyed by env.
  • terraform import to adopt 200 dusty resources from console clicks.
  • State rollback via backend object version when a bad apply sweeps a resource.
Guidelines

Best practices

  • Remote + locked backend for every team; local state only for throwaway demos.
  • Keep state read permission narrow; treat it as secrets (encrypt).
  • Never hand-edit state; use the tool's surgery commands or a careful recovery.
  • Add drift checks: scheduled plan+diff alerts when state reality diverges from code.
  • Document the backend + who owns it in every repo's README.
Watch out

Common mistakes

  • Storing state in git (the .tfstate-in-repo legendary footgun).
  • No lock table → two applies race and both think they won.
  • Import without a post-import plan review → surprise force-new cascades.
  • state rm used as a dirty delete → real resources orphaned and now untracked.
When things break

Debugging tips

  • Plan shows delete+create of something stable → check for a state identity mismatch (ids/ARN).
  • Out-of-band change made in console but plan shows nothing → state/permissions hide it; refresh to see reality.
  • Concurrent apply errors → inspect the lock table's LeaseID entry and break stale leases cautiously.
  • State read blocked → IAM/bucket policy; verify the exact backend key exists.
Interviews

Interview checkpoint

Practice

Hands-on lab

Share and Lock State Across Two Runs
40 min · advanced
In progress
Objectives
  • Configure a remote backend with locking
  • Simulate concurrent applies and watch the lock work
  • Recover/rollback from a versioned state

Share and Lock State Across Two Runs

40 min · advanced

0/4 steps
0%
sandbox · Linux sandbox
$
Try these commands
Test yourself

Quick quiz

0/2
1

Two engineers running apply on a shared remote backend without locking:

2

Adopting a hand-created resource into code's graph uses:

Go deeper

Official documentation