Cloud  /  Terraform

IaC Terraform 50 guides · updated 2026

Infrastructure as code done right — providers, state, reusable modules, and the workflow patterns that keep multi-cloud deployments sane in 2026.

Terraform State File

Terraform’s state file (terraform.tfstate) is the source of truth that maps your configuration to real-world infrastructure. Without it, Terraform cannot determine what exists, what needs to change, or what to destroy. Understanding how it works is fundamental to operating Terraform safely.


What the State File Does

Terraform uses the state to:

  1. Track resource identity — which cloud resource corresponds to which block in your config
  2. Cache resource attributes — avoid fetching data from the provider API on every plan
  3. Detect drift — compare desired (config) vs actual (state) vs real (provider) state
  4. Manage dependencies — know the correct destroy order when resources depend on each other

State File Structure

{
"version": 4,
"terraform_version": "1.9.5",
"serial": 12,
"lineage": "3b2b3b2b-...",
"outputs": {
"vpc_id": {
"value": "vpc-0abc123def456789",
"type": "string"
}
},
"resources": [
{
"mode": "managed",
"type": "aws_vpc",
"name": "main",
"provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
"instances": [
{
"schema_version": 1,
"attributes": {
"id": "vpc-0abc123def456789",
"cidr_block": "10.0.0.0/16",
"tags": {
"Environment": "production",
"Name": "main-vpc"
}
}
}
]
}
]
}

Key fields:


State Commands

Terminal window
# List all resources in state
terraform state list
# Show details for a specific resource
terraform state show aws_vpc.main
terraform state show 'aws_instance.workers[0]'
terraform state show 'module.app.aws_ecs_service.main'
# Move a resource to a new address (refactoring)
terraform state mv aws_instance.app aws_instance.web
# Move a resource into a module
terraform state mv aws_s3_bucket.logs module.storage.aws_s3_bucket.logs
# Remove a resource from state (stops managing it, doesn't destroy it)
terraform state rm aws_instance.legacy
# Pull current remote state and print it locally
terraform state pull
# Push a local state to the remote backend (use with caution)
terraform state push terraform.tfstate

Local State (Default)

By default, Terraform creates terraform.tfstate in the working directory:

my-infra/
├── main.tf
├── variables.tf
├── terraform.tfstate ← Created after first apply
├── terraform.tfstate.backup ← Previous state (auto-created)
└── .terraform/

Local state problems:


Why State Must Be Protected

State files often contain sensitive values:

"attributes": {
"password": "actualDatabasePassword123!",
"access_key": "AKIAIOSFODNN7EXAMPLE",
"secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
}

sensitive = true in your config only hides values from CLI output — the plaintext value still lives in state.

Protect state by:

  1. Using remote state with encryption (S3 + KMS, Terraform Cloud)
  2. Restricting IAM access to the state bucket
  3. Never committing .tfstate files to git — add to .gitignore
.gitignore
*.tfstate
*.tfstate.*
.terraform/

Remote State: The Production Standard

terraform {
backend "s3" {
bucket = "mycompany-terraform-state"
key = "production/terraform.tfstate"
region = "us-east-1"
encrypt = true
kms_key_id = "arn:aws:kms:us-east-1:123456789012:key/mrk-..."
dynamodb_table = "terraform-state-lock"
}
}

Remote state provides:


State File Versioning and Backup

Enable S3 versioning to protect against accidental state corruption:

resource "aws_s3_bucket_versioning" "state" {
bucket = aws_s3_bucket.terraform_state.id
versioning_configuration {
status = "Enabled"
}
}

To restore a previous state version:

Terminal window
# List state versions
aws s3api list-object-versions \
--bucket mycompany-terraform-state \
--prefix "production/terraform.tfstate"
# Download a previous version
aws s3api get-object \
--bucket mycompany-terraform-state \
--key "production/terraform.tfstate" \
--version-id "abc123..." \
terraform.tfstate.restore
# Push the restored state back (with care)
terraform state push terraform.tfstate.restore