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 both use_lockfile and dynamodb_table during 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

CommandWhat it does
terraform showhuman-readable state dump
terraform show -jsonmachine-readable state
terraform state listlist 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 pulldownload 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 refreshupdate 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.tfstate

Importing 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 operation

Remote 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 .tfstate files 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.