Terraform Cheatsheet
State
Use this Terraform reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.
What State Is
Terraform keeps a terraform.tfstate JSON file that maps your config to real infrastructure. It tracks resource IDs, attributes, dependencies, and metadata. State is the source of truth — never edit it by hand.
Backends
A backend determines where state is stored and how operations run.
S3 Backend (most common for AWS)
terraform {
backend "s3" {
bucket = "my-tf-state"
key = "prod/us-east-1/terraform.tfstate"
region = "us-east-1"
encrypt = true
use_lockfile = true # S3-native locking (GA in Terraform 1.10)
}
}Legacy:
dynamodb_table = "tf-state-lock"was the original S3 locking mechanism; it is deprecated since Terraform 1.11. Set bothuse_lockfileanddynamodb_tableduring migration, then drop the DynamoDB table.
HCP Terraform (cloud block)
terraform {
cloud {
organization = "my-org"
workspaces {
name = "prod"
}
}
}HCP Terraform (formerly Terraform Cloud) stores state, runs plans/applies remotely, and handles locking — no bucket setup.
GCS Backend (GCP)
backend "gcs" { bucket = "my-tf-state" prefix = "terraform/state" }
Azure Backend
backend "azurerm" { resource_group_name = "tf-state-rg" storage_account_name = "mytfstate" container_name = "tfstate" key = "prod.terraform.tfstate" }
Local Backend (default, dev only)
backend "local" { path = "terraform.tfstate" }
Never use local state in teams — no locking, no sharing.
State Commands
| Command | What it does |
|---|---|
terraform show | human-readable state dump |
terraform show -json | machine-readable state |
terraform state list | list all tracked resources |
terraform state show <address> | show one resource's attributes |
terraform state mv <src> <dst> | rename/move a resource in state |
terraform state rm <address> | remove resource from state (orphan it) |
terraform state pull | download remote state to stdout |
terraform state push <file> | upload a state file to remote backend |
terraform force-unlock <lock-id> | release a stuck state lock |
terraform refresh | update state to match real infrastructure |
# Examples
terraform state list
terraform state show aws_instance.web
terraform state mv aws_instance.web aws_instance.app_server
terraform state rm aws_s3_bucket.old_bucket
terraform state pull > backup.tfstateImporting Existing Resources
1.5+: import block in config (preferred — shows in plan):
import { to = aws_instance.web id = "i-0abcd1234efgh5678" }
# Generate config for resources declared in import blocks (1.5+) terraform plan -generate-config-out=imported.tf # Classic one-shot import command terraform import aws_instance.web i-0abcd1234efgh5678
Moving Resources (1.1+ moved block)
# Rename a resource without destroying and recreating it
moved {
from = aws_instance.old_name
to = aws_instance.new_name
}
# Move into a module
moved {
from = aws_instance.web
to = module.servers.aws_instance.web
}Removing Resources from State (1.7+ removed block)
Forget a resource (stop managing it) without destroying it — the declarative replacement for terraform state rm:
removed {
from = aws_instance.web
lifecycle {
destroy = false # keep the real infrastructure
}
}State Locking
State is locked automatically during plan, apply, destroy. If a lock gets stuck (crashed process):
terraform force-unlock LOCK_ID
# Lock ID is shown in the error message from the failed operationRemote State Data Source
Read outputs from another Terraform state without copy-pasting values.
data "terraform_remote_state" "vpc" { backend = "s3" config = { bucket = "my-tf-state" key = "shared/vpc/terraform.tfstate" region = "us-east-1" } } resource "aws_instance" "app" { subnet_id = data.terraform_remote_state.vpc.outputs.public_subnet_ids[0] }
Workspace-Specific State Keys
Each workspace gets its own state file:
s3://bucket/ ├── env:/ │ ├── staging/terraform.tfstate │ └── prod/terraform.tfstate └── terraform.tfstate # default workspace
Sensitive Values in State
State files store all attribute values in plain text — including passwords and secrets. Protect your state:
- Encrypt the backend bucket/container
- Restrict IAM/ACL access to the state bucket
- Never commit
.tfstatefiles to git - Add
*.tfstate*to.gitignore
Partial Configuration (external backend config)
# backend.hcl bucket = "my-tf-state" key = "prod/terraform.tfstate" region = "us-east-1"
terraform init -backend-config=backend.hcl
Useful when the bucket name or key changes per environment.