Guide

Terraform does not scan your whole cloud account on each run. It keeps a state file: a JSON map from each resource address, such as aws_s3_bucket.assets, to the real cloud ID and attributes. Without that map, Terraform cannot tell which real resources it owns.

Concept

Before you start. Read plan and apply. A plan is the desired config compared with the state, refreshed against the cloud API.

The big idea

Think of state as a hotel's check-in list. It maps each guest name to a room number. The list is useful because the desk can answer quickly without walking every floor.

Where the analogy breaks: the list can be wrong. A guest may leave without telling the desk, and that is drift. Terraform fixes only what it can see, so the list must stay accurate.

Local state and remote backends

Local state (terraform.tfstate on disk) is fine for a laptop experiment. For a team it is risky. It has no locking, it is easy to lose, and people often commit it to git. State can contain passwords and private keys.

Use a remote backend. This example stores state in an S3 bucket:

hcl
terraform {
  backend "s3" {
    bucket       = "acme-tf-state"
    key          = "prod/payments/terraform.tfstate"
    region       = "us-east-1"
    encrypt      = true
    use_lockfile = true   # native S3 locking (Terraform 1.9+)
  }
}

You need three properties: durable storage, encryption at rest, and locking.

Walking through a race without a lock

Two applies start at the same time, with no lock.

Apply A reads state:   bucket, no versioning
Apply B reads state:   bucket, no versioning
Apply A writes state:  bucket, versioning on
Apply B writes state:  bucket, tags added     <- A's write is lost

The bucket still has versioning, but state no longer records it. The next plan may try to undo the setting or miss it. That is classic drift, and it is hard to untangle later.

State surgery

Sometimes you must edit the map without changing the cloud.

CommandUse when
terraform importThe resource already exists and should be managed
terraform state mvYou renamed a resource address in code
terraform state rmStop managing a resource, but leave it running
terraform refreshRe-read remote attributes into state

Renaming a resource in code without a move makes the next plan destroy the old address and create a new one. For a database, that means a new, empty instance. The fix is a move:

Bash
terraform state mv aws_db_instance.main aws_db_instance.primary
terraform plan
No changes. Your infrastructure matches the configuration.

After any surgery, the plan should show no changes. If it does not, stop and read it.

Common mistakes

  • Committing state to git. If it leaks, rotate the secrets in it, then move to a remote backend.
  • Running two applies at once without a lock. One write silently overwrites the other.
  • Editing state and not checking the plan afterward. A wrong import attaches the wrong object to a name.

Check yourself

  1. Why can't Terraform rely only on your code? Answer: it needs the state to know which real resource each address refers to, and which ones it created.
  2. You renamed a resource in code. Which command stops a destroy? Answer: terraform state mv from the old address to the new one, then confirm the plan shows no changes.

Key takeaways

  • State maps each resource address to a real ID. Plans depend on it.
  • Use a remote backend with encryption and locking.
  • Treat import, mv and rm with the care of a data migration.
  • Next, modules and environments shows how to split state across environments.

Further learning

State (Terraform docs)An introduction to state, information that Terraform uses to map resources to a configuration, track metadata, and improve performance.State | Terraform | HashiCorp Developer The s3 backend (Terraform docs)Terraform can store and lock state remotely in Amazon S3.Backend Type: s3 | Terraform | HashiCorp Developer How to manage Terraform state (Gruntwork)Managing Terraform state: a guide to file layout, isolation, and locking for Terraform projects, part of the Comprehensive Guide to Terraform series.blog.gruntwork.io Importing existing resources (Terraform docs)Learn about importing existing infrastructure resources to your Terraform workspace using the bulk import workflow or the single-resource import workflowImport resources overview | Terraform | HashiCorp Developer