Curious Devs Corner

Curious Devs Corner

Share this post

Curious Devs Corner
Curious Devs Corner
Terraform Quickstart: Part 6 – Managing Terraform State
Mini-Courses

Terraform Quickstart: Part 6 – Managing Terraform State

Learn How Terraform State Works and How to Avoid Infrastructure Drift

KirshiYin's avatar
KirshiYin
Jun 17, 2025
∙ Paid

Share this post

Curious Devs Corner
Curious Devs Corner
Terraform Quickstart: Part 6 – Managing Terraform State
Share

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:

  1. State backups: Terraform automatically creates .tfstate.backup files

  2. Remote state with versioning: S3 or other backends with versioning enabled

  3. Terraform import: Recreate state by importing existing resources

  4. 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

Curious Devs Corner is a reader-supported publication. To receive new posts and support my work, consider becoming a free or paid subscriber.

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.

Already a paid subscriber? Sign in
© 2025 Kirshi Yin
Privacy ∙ Terms ∙ Collection notice
Start writingGet the app
Substack is the home for great culture

Share