Terraform State Explained: Remote State, Locking, Backends and Best Practices

Terraform

Terraform state is the snapshot Terraform uses to map your code to real infrastructure. If you understand how the state file works, where to store it, and how to protect it, you can avoid drift, broken applies, and team collisions.

This guide explains Terraform state end to end: what lives in the tfstate file, when to use remote backends, how locking works, how to review drift safely, and which commands matter when you need to inspect or refactor state. If you need the AWS-specific migration procedure, jump to Move Terraform State Between AWS Accounts. If you want a short explainer focused only on the state file itself, see What Is a Terraform State File (tfstate)?.

What is Terraform state?

Terraform state is Terraform’s record of the resources it manages. It lets Terraform compare your configuration with the real infrastructure and decide what to create, update, replace, or destroy.

  • It maps resource blocks in your code to real cloud resources.
  • It stores metadata and dependencies so Terraform can plan changes safely.
  • It exposes outputs that other configurations may consume.
  • It becomes the system of record for collaborative Infrastructure as Code workflows.

What is stored in the state file?

The state file usually contains resource IDs, attributes returned by the provider, dependency information, outputs, and bookkeeping data such as lineage and serial numbers. In practice, that means state can contain sensitive values, which is one reason teams should treat it as operational data rather than a harmless text file.

Do not edit the state file by hand unless you are dealing with a controlled break-glass situation and you have a backup. For normal changes, let Terraform update state through plan, apply, import, state mv, and related commands.

Local state vs remote state

When local state is acceptable

Local state is acceptable for short-lived labs, isolated experiments, and personal proof-of-concept work. It is simple and requires no backend setup.

Why remote state is better for real environments

For shared environments, remote state should be the default. A remote backend gives your team a consistent location for state, reduces the risk of losing the file with a laptop, and usually gives you stronger security and access control.

  • Centralized access for teams and CI pipelines.
  • Better protection for sensitive values.
  • Reduced risk of state drift caused by people using different local copies.
  • Safer operations when the backend supports locking.

How locking and collaboration work

State locking prevents multiple writers from changing the same state at the same time. If your backend supports locking, Terraform acquires a lock before write operations and releases it when the operation completes. This is one of the key reasons remote state is safer for teams.

If a process fails and leaves a stale lock behind, you can use terraform force-unlock. Treat that as a recovery action, not a routine workflow, because forcing unlocks at the wrong time can create conflicting writers.

How to review drift safely

Terraform plan and apply already perform an implicit refresh before proposing changes. If you need to reconcile state with live infrastructure without changing the infrastructure itself, prefer terraform plan -refresh-only or terraform apply -refresh-only rather than relying on the older terraform refresh workflow.

This is especially useful when you suspect manual changes were made outside Terraform and you want to understand the drift before you commit any updates to the state file.

Common Terraform state commands

These commands are worth knowing when you need to inspect or refactor state:

terraform state list
terraform state show aws_instance.example
terraform state pull
terraform state mv old.address new.address
terraform state rm aws_instance.example

Use them carefully. Commands such as state mv and state rm are powerful, but they directly affect Terraform’s understanding of your infrastructure.

Backend examples

A minimal S3 backend setup on AWS can look like this:

terraform {
  backend "s3" {
    bucket = "my-terraform-state-bucket"
    key    = "networking/prod/terraform.tfstate"
    region = "eu-west-1"
  }
}

A Google Cloud Storage backend uses a different backend type and configuration:

terraform {
  backend "gcs" {
    bucket = "my-terraform-state-bucket"
    prefix = "networking/prod"
  }
}

Keep credentials out of your code where possible. Use your platform’s standard authentication mechanisms, secret stores, and CI credentials rather than hardcoding access keys into backend configuration files.

Security best practices

  • Store state remotely for production and team environments.
  • Encrypt backend storage and apply least-privilege access controls.
  • Assume the state file may contain sensitive values.
  • Avoid printing sensitive outputs in logs or terminals unless necessary.
  • Back up state before risky refactors or migrations.

Terraform state best practices for teams

  1. Move off local state early once a project becomes shared or important.
  2. Use one backend strategy per environment and document it clearly.
  3. Protect writes with a locking-capable workflow.
  4. Keep backend configuration and IAM access simple enough for operators to troubleshoot.
  5. Use state mv and import when refactoring instead of deleting and recreating resources.
  6. Validate drift with -refresh-only workflows before making bigger changes.
  7. Document migration procedures for state moves, especially between accounts or environments.

Related Terraform guides

Use this page as the main reference for Terraform state. Then branch out to the supporting guides when you need AWS migration steps, plan file workflows, or narrower Terraform topics.

Elsewhere On TurboGeek:  How to Install Glances on RHEL 9/8, Rocky Linux and AlmaLinux

Want more of this kind of guide?

Use the blog and category routes to keep moving through the archive, or support TurboGeek if the site saves you time regularly.

Translate ยป