Intermediate · Infrastructure as code with Terraform · topic 32 of 53 · 30 min
Terraform state, backends and drift
Explanation
What state is and why Terraform needs it
Your code says "there is a bucket called aws_s3_bucket.logs". The cloud has a bucket with the real name college-logs-prod. Terraform needs a record that links the two. That record is the state, stored by default in a file called terraform.tfstate (JSON). It holds the resource address, the real ID and the last known attributes of everything Terraform manages.
At every plan, Terraform reads the state, refreshes it by asking the cloud for the current values, and compares the result with your code. Without state, Terraform would not know which real bucket is "its" bucket, and it would try to create everything again.
Why state is sensitive
State stores attributes in plain text. That includes database passwords, private keys created by Terraform, and connection strings, even for values marked sensitive. Anyone who can read the state file can read those secrets. Treat state like a password vault.
# .gitignore for a Terraform project
.terraform/
*.tfstate
*.tfstate.*
crash.log
*.tfvars # only if your tfvars files hold secrets; commit safe example files instead
override.tf
override.tf.jsonLocal versus remote backends
A backend is where state lives. The default local backend writes terraform.tfstate on your laptop. That breaks in a team: your colleague does not have your file, and if your laptop dies the state is gone. A remote backend stores state in shared, durable storage with access control and encryption.
| Backend | Where state lives |
|---|---|
| s3 | An Amazon S3 bucket (turn on versioning and encryption) |
| azurerm | An Azure Storage account blob container |
| gcs | A Google Cloud Storage bucket |
| HCP Terraform (formerly Terraform Cloud) | HashiCorp's hosted service, configured with a cloud block |
terraform {
backend "s3" {
bucket = "acme-terraform-state"
key = "network/prod/terraform.tfstate"
region = "ap-south-1"
encrypt = true
use_lockfile = true # native S3 locking in newer Terraform versions; check the docs for yours
}
}State locking
If two engineers run apply at the same moment, both read the same old state and both write a new one. One change is lost and the state may be corrupted. Locking prevents this: the first apply takes a lock, and the second waits or fails with "Error acquiring the state lock". Newer Terraform versions can lock with a lock file in the S3 bucket itself (use_lockfile = true). The older way used a DynamoDB table, which is now deprecated. azurerm and gcs backends lock natively, and HCP Terraform handles it for you.
Working with state safely
terraform state list # every address in state
terraform state show aws_s3_bucket.logs # stored attributes of one resource
terraform state mv aws_s3_bucket.logs aws_s3_bucket.app_logs # you renamed it in code
terraform state rm aws_s3_bucket.legacy # forget it; the real bucket is NOT deletedNewer Terraform also lets you do these moves in code: a moved block records a rename, and a removed block forgets a resource. They are reviewed in a pull request like any other change, which is safer than running commands by hand.
Importing existing resources
Often a resource was created by hand before IaC. An import block (Terraform 1.5 and later) adopts it into state, so Terraform manages it from now on. terraform plan -generate-config-out=generated.tf can even write a first draft of the resource block for you to clean up.
import {
to = aws_s3_bucket.logs
id = "college-logs-prod"
}Drift
Drift means the real infrastructure no longer matches the state, usually because someone changed it in the console. A normal plan detects drift and proposes to change it back to match the code. terraform plan -refresh-only shows only what changed outside Terraform, without proposing to fix it, and terraform apply -refresh-only updates state to accept reality. Then decide: either update the code to match, or let the next apply restore the code's version.
Common mistakes
Need help?
Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.
Try:
Watch the lesson
Terraform state, backends and drift · 1/7
In this lesson you will learn what Terraform state is, where to keep it, and how to handle drift.
Prefer a video by a teacher? Find free videos on “terraform state remote backend s3 locking drift explained” on YouTube ↗
In real life: Drift at a hospital chain
A hospital chain in Chennai manages its patient-portal security groups with Terraform. During a night incident, an engineer opens port 22 to 0.0.0.0/0 in the console and forgets to close it. The nightly CI job runs terraform plan -refresh-only, sees the changed ingress rule and posts an alert to the team channel. The next morning the team runs a normal apply, which puts the rule back to the reviewed version in code.
terraform plan -refresh-only -detailed-exitcode
# exit code 0 = no drift, 2 = drift found, 1 = errorPractice (0/3 done)
Which file should NOT be committed to Git?
Detect drift. state and real are dicts of attributes for one resource (what Terraform recorded, and what the cloud reports now). Write find_drift(state, real) that returns a sorted list of keys whose values differ, including keys that exist in only one of the two dicts.
You renamed resource aws_instance.web to aws_instance.frontend in code. Plan wants to destroy one and create one. What is the right fix?
Quick quiz
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- Modules, environments and Terraform in CIInfrastructure as code with Terraform · same module
- Terraform for the cloudCloud Computing (AWS, Azure, Google Cloud) · Infrastructure as code
- IaC in a team: reviews, pipelines and policyCloud Computing (AWS, Azure, Google Cloud) · Infrastructure as code
- Why infrastructure as codeCloud Computing (AWS, Azure, Google Cloud) · Infrastructure as code
- AWS vs Azure vs Google Cloud: the service mapCloud Computing (AWS, Azure, Google Cloud) · Google Cloud and comparing the clouds
- AWS CloudFormationCloud Computing (AWS, Azure, Google Cloud) · Infrastructure as code
Questions people ask about this
Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.
What does state locking protect against?
Answer: Two applies writing the same state at the same time
Locking makes the second apply wait or fail, so changes are not lost and state is not corrupted.
What does terraform state rm aws_s3_bucket.legacy do to the real bucket?
Answer: Nothing: Terraform just stops tracking it
state rm only removes the record. The real resource keeps existing.
Which command shows changes made outside Terraform without proposing to undo them?
Answer: terraform plan -refresh-only
A refresh-only plan compares state with reality and reports drift only.
A bucket was created by hand last year. How do you bring it under Terraform without recreating it?
Answer: Use an import block (or terraform import), then plan and apply
Import adopts an existing object into state. A plain resource block would try to create a new one.
Why turn on versioning for the S3 bucket that stores state?
Answer: You can roll back to an older state if one gets corrupted
Versioning keeps earlier copies of the state file, a safety net for mistakes.
Why should terraform.tfstate not be committed to Git?Related
Answer: It can contain secrets in plain text and it must be shared with locking, which Git cannot do
State can hold passwords and keys, and it needs locking to stop two applies at once. Use an encrypted remote backend.
Your company has 200 resources that were created in the console. What is the usual way to bring them under Terraform?Related
Answer: Import them (import blocks or terraform import), then plan until it shows no changes
Importing adds existing resources to the state; a clean plan proves the code matches them.
Which statement about Terraform and OpenTofu is correct?Related
Answer: Terraform moved to the Business Source License in 2023, and OpenTofu is an open-source fork under the Linux Foundation
HashiCorp changed Terraform to BSL 1.1 in August 2023. OpenTofu forked the last open-source version.
How do you refer to the id of resource "aws_s3_bucket" "logs"?Related
Answer: aws_s3_bucket.logs.id
A resource address is TYPE.NAME, and you add the attribute after another dot.
From Terraform basics: HCL, providers, resources and the workflow
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.
Next steps
- 1 more topic in “Infrastructure as code with Terraform” before its exam: Modules, environments and Terraform in CI.
- Module 7 exam: Infrastructure as code with Terraform · 13 questions · 20 min, without help. 4 topics of this module still to finish first.
- Then the next module, Configuration management with Ansible, and YAML. 53 topics left in the course before the final exam.
← Previous: Terraform basics: HCL, providers, resources and the workflow