Skip to main content
Terraform State Management and Locking Guide

Terraform State Management and Locking Guide

Key Takeaway

Master Terraform state management: remote backends, state locking with DynamoDB, state commands, sensitive data, and team collaboration best practices.

Table of Contents

Quick Answer

Terraform state tracks every resource you manage. Store it remotely (S3, Azure Blob, GCS) with locking (DynamoDB, native) to enable team collaboration and prevent corruption. Never edit state files manually — use terraform state commands.

What is Terraform State?

The state file (terraform.tfstate) is a JSON file that maps your HCL configuration to real cloud resources:

{
  "resources": [{
    "type": "aws_instance",
    "name": "web",
    "instances": [{
      "attributes": {
        "id": "i-1234567890abcdef0",
        "ami": "ami-0abcdef1234567890",
        "instance_type": "t3.micro",
        "public_ip": "54.123.45.67"
      }
    }]
  }]
}

Without state, Terraform can’t know which cloud resources it created, what to update, or what to destroy.

Local vs Remote State

FeatureLocal (terraform.tfstate)Remote (S3/Azure/GCS)
Team access❌ Single machine✅ Shared
Locking❌ None✅ DynamoDB/native
Encryption❌ Plaintext✅ At rest
Versioning❌ No history✅ Rollback
CI/CD❌ Needs file sharing✅ Native
Risk of loss❌ Laptop crash = gone✅ Cloud durability

Configure Remote State with Locking

AWS S3 + DynamoDB

terraform {
  backend "s3" {
    bucket         = "mycompany-terraform-state"
    key            = "prod/app/terraform.tfstate"
    region         = "us-east-1"
    dynamodb_table = "terraform-locks"
    encrypt        = true
  }
}

Azure Blob Storage

terraform {
  backend "azurerm" {
    resource_group_name  = "terraform-rg"
    storage_account_name = "tfstatemycompany"
    container_name       = "tfstate"
    key                  = "prod.terraform.tfstate"
  }
}

GCP Cloud Storage

terraform {
  backend "gcs" {
    bucket = "mycompany-terraform-state"
    prefix = "prod/app"
  }
}

How State Locking Works

  1. terraform apply starts → requests a lock
  2. Lock acquired → proceeds with changes
  3. Another user runs apply → sees “Error acquiring state lock” → waits
  4. First apply finishes → lock released → second user can proceed
# If a lock gets stuck (crashed process, lost connection):
terraform force-unlock LOCK_ID
# Get LOCK_ID from the error message

Essential State Commands

# List all resources in state
terraform state list

# Show details of one resource
terraform state show aws_instance.web

# Move a resource (rename without destroy/recreate)
terraform state mv aws_instance.web aws_instance.app

# Remove from state (resource stays in cloud, Terraform forgets it)
terraform state rm aws_instance.web

# Import existing resource into state
terraform import aws_instance.web i-1234567890abcdef0

# Pull remote state to local file (backup)
terraform state pull > backup.tfstate

# Push local state to remote (dangerous — use carefully)
terraform state push backup.tfstate

# Refresh state from cloud (sync drift)
terraform apply -refresh-only

State and Sensitive Data

State files contain everything — including passwords, API keys, and connection strings:

# This is in your state file in plaintext:
# "password": "super-secret-db-password"

Protect state with:

  • Encryption at rest (S3 SSE-KMS, Azure encryption, GCS encryption)
  • Access control (IAM policies restricting who can read state)
  • Never commit to git — add *.tfstate to .gitignore
  • Never share state files via email or chat

State File Organization

Split state by environment and component to reduce blast radius:

# One giant state = high risk
prod/everything/terraform.tfstate  ← one bad apply affects everything

# Split state = low risk
prod/networking/terraform.tfstate   ← VPC, subnets, security groups
prod/database/terraform.tfstate     ← RDS, ElastiCache
prod/compute/terraform.tfstate      ← EC2, ASG, ALB
prod/dns/terraform.tfstate          ← Route53

Common Issues

ProblemSolution
“Error acquiring state lock”Wait for other apply, or force-unlock
State file corruptedRestore from S3 versioning
Drift (cloud ≠ state)terraform apply -refresh-only
Resource in wrong state fileterraform state mv -state-out=other.tfstate
Need to see what’s in stateterraform state list then terraform state show

Best Practices

  • Always use remote state for team projects
  • Enable versioning on state bucket — your disaster recovery
  • Enable encryption — state contains secrets
  • Split state by component — smaller blast radius
  • Never edit state JSON manually — use terraform state commands
  • Use prevent_destroy on state storage resources
  • Run terraform plan before apply — always review changes

Hands-On Courses

Conclusion

Terraform state is the single source of truth for your infrastructure. Store it remotely with locking and encryption, never edit it manually, split it by component, and treat it like a database — because it is one. Master terraform state commands and you’ll handle any state issue that comes up.

🚀

Level Up Your Terraform Skills

Hands-on courses, books, and resources from Luca Berton

Luca Berton
Written by

Luca Berton

DevOps Engineer, AWS Partner, Terraform expert, and author. Creator of Ansible Pilot, Terraform Pilot, and CopyPasteLearn.