Terraform Quickstart: Part 6 – Managing Terraform State
Learn How Terraform State Works and How to Avoid Infrastructure Drift
Introduction
Imagine a teammate removes a resource directly from the cloud provider’s dashboard—let’s say an S3 bucket on AWS. But Terraform doesn’t know that. The next time someone runs terraform apply
, it sees the bucket is missing and tries to recreate it. That might be fine—or it might overwrite something important or break dependencies.
This happens because Terraform relies on its state file to track what exists. If the state and the actual infrastructure go out of sync, you risk bugs, downtime, or data loss.
That’s why understanding and managing Terraform state is so important.
In this chapter, you'll learn how Terraform keeps track of your infrastructure. You'll also learn how to avoid common mistakes that can cause problems in real-world projects. You’ll get experience with Terraform Cloud using a free account.
How does Terraform State Work?
Terraform keeps track of what it has created using a state file (terraform.tfstate
).
When Terraform creates resources, it stores the details (resource IDs, settings, etc.) in this state file. This is the typical workflow:
Without a state, Terraform can't recognize existing resources—resulting in errors like trying to create resources that already exist.
Local State vs. Remote State
Terraform supports two ways to store state:
Local state - stored on your filesystem. Suitable for personal or temporary projects.
Remote state - stored on a cloud storage/service. Good for teams, automation, or CI/CD pipelines.
Why not use Local State for CI/CD Pipelines?
Local state files get deleted after the pipeline runs, causing resource conflicts.
Remote state solves this by persisting the state across runs, enabling collaboration and automation.
State Inspection
You can examine the current state using the following commands:
$ terraform state list
Example output:
terraform state list
data.github_repository.existing_repo
data.github_repository.website_repo
$ terraform state show data.github_repository.existing_repo # print information about a specific state
When troubleshooting, these commands help understand what Terraform thinks exists.
State Disaster Recovery
If state becomes corrupted or lost, you can recover using:
State backups: Terraform automatically creates
.tfstate.backup
filesRemote state with versioning: S3 or other backends with versioning enabled
Terraform import: Recreate state by importing existing resources
Terraform refresh: Update state to match real-world resources
# Recreate state file from backup
$ cp terraform.tfstate.backup terraform.tfstate
# Update state to match real-world
$ terraform refresh
Hands-on Exercise: Managing Remote State with Terraform Cloud as Backend
Update your GitHub Actions workflow file from the previous chapter (terraform.yml
) to handle the Terraform state:
name: Terraform CI/CD Automation
on:
push:
branches: [main]
paths:
- 'terraform/**'
pull_request:
branches: [main]
paths:
- 'terraform/**'
jobs:
terraform:
runs-on: ubuntu-latest
defaults:
run:
working-directory: terraform
env:
TF_VAR_github_token: ${{ secrets.TF_VAR_github_token }}
TF_VAR_github_owner: ${{ github.repository_owner }}
TF_API_TOKEN: ${{ secrets.TF_API_TOKEN }}
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Setup Terraform CLI
uses: hashicorp/setup-terraform@v2
with:
terraform_version: 1.6.6
cli_config_credentials_token: ${{ secrets.TF_API_TOKEN }}
- name: Terraform Initialization
run: terraform init
- name: Terraform Validate
run: terraform validate
- name: Terraform Plan
run: terraform plan -input=false
- name: Terraform Apply
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
run: terraform apply -auto-approve -input=false
Add your Terraform Cloud configuration to the backend.tf
:
terraform {
cloud {
organization = "your-organization-name"
workspaces {
name = "your-gitlab-project"
}
}
}
Set Up Your Terraform Cloud Workspace
Keep reading with a 7-day free trial
Subscribe to Curious Devs Corner to keep reading this post and get 7 days of free access to the full post archives.