Skip to main content

Command Palette

Search for a command to run...

Terraform State Management

Updated
5 min read

Video reference: here

Check out the previous blog if not: S3 Bucket creation using Terraform.


Understanding Terraform State Updates

We will look into how Terraform updates its infrastructure.

Here, the DevOps engineer updates the desired state through terraform apply. The state file will keep track of the resources in the local system state to the state in actual state, and then it leads to the changes in the infrastructure.

Terraform maintains infrastructure by keeping the actual state synchronised with the desired state defined in configuration files.

Here, the DevOps engineer will be

  1. Run terraform apply and it updates any changes to terraform.tfstate file.

  2. Terraform compares the current state with the desired configuration (actual state)

  3. Only resources requiring modification are updated

We always make sure that Desired state == Actual state.

Primarily, we can’t just call the infrastructure directly to make changes. The terraform.tfstate file is easier to manage our infrastructure.

Also this file shouldn’t be open to publishing or exposing. This is kind of secret and contains a lot of confidential information.

The Terraform state file is a JSON document containing:

  • Resource metadata and current configuration

  • Resource dependencies and relationships

  • Provider information

  • Resource attribute values

The state file serves as Terraform's source of truth for tracking managed infrastructure.

State File and Remote Backend

Every time we perform a tf command (tf == terraform). Instead of checking the local state file, we can look at the changes in a remote backend. This can be any storage, no need to be S3, blob, or GCP cloud storage.

By default, Terraform will use the local state file as a single source of truth. Remote backend is a feature in Terraform. We can use it to trigger more resources and manage the infrastructure well.

Import points to remember:

  1. Store the state file in a remote backend

  2. Do not update/delete the file

  3. State locking (If a process executes the infrastructure, never allow any other process to use the state file at the same time on the same infrastructure. Like a package manager in Linux. Mutual exclusion principle)

  4. Isolation of statefile

  5. Regular backup

State File Best Practices

  1. Never edit state files manually: Manual edits can corrupt state tracking and cause infrastructure drift.

  2. Store state files remotely: Local storage prevents team collaboration and creates single points of failure.

  3. Enable state locking: Prevents concurrent modifications that could corrupt state or cause conflicts.

  4. Backup state files regularly: State loss can make infrastructure unmanageable.

  5. Use separate state files per environment: Isolate development, staging, and production states.

  6. Restrict access to state files: State files contain sensitive data, including passwords, API keys, and connection strings.

  7. Encrypt state files: Enable encryption both at rest and in transit.

Remote Backend Bene

  1. Collaboration: Multiple team members can access the shared state safely.

  2. State Locking: Prevents simultaneous modifications from multiple users or processes.

  3. Security: Centralised access control and encryption capabilities.

  4. Backup and Versioning: Automatic state versioning enables rollback if needed.

  5. High Availability: Remote storage services provide durability and availability guarantees.

S3 - State Locking

Go to the docs. We will use the given example in the official documentation and modify the code.

But before we do this, we need to make sure that the bucket exists. Or else, we will get this error:

  • Error: Failed to get existing workspaces: S3 bucket "bucket-name" does not exist. When you run terraform init

Go to the AWS console, choose the location as us-east-1 and create a bucket you want. Create a main.tf file in your desired local system. Make sure the bucket you are storing the state file should is a different bucket from what you created.

# backend configuration
terraform {
  backend "s3" {
    bucket = "amal-s3-bucket-terraform30days-1"
    key    = "dev/terraform.tfstate"
    region = "us-east-1"
    encrypt = true
    use_lockfile = true
  }
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 6.0"
    }
  }
}

provider "aws" {
  region = "us-east-1"
}

resource "aws_s3_bucket" "first_s3_bucket" {
  bucket = "amal-s3-bucket-terraform30days"

  tags = {
    Name        = "My bucket 2.0"
    Environment = "Dev"
  }
}

Key Parameters:

  • bucket: S3 bucket name for state storage

  • key: Path within the bucket where the state file will be stored

  • region: AWS region for the S3 bucket

  • use_lockfile: Enable S3 native state locking (set to true)

  • encrypt: Enable server-side encryption for the state file

After that, you should run:

terraform init

This will output to:

Initializing the backend...

Successfully configured the backend "s3"! Terraform will automatically
use this backend unless the backend configuration changes.
....................

If it’s all good, run:

terraform plan
terraform apply

This will create a new bucket with the name we intended to create using Terraform. Now, there are two S3 buckets in our hands.

  1. Work as a remote backend

  2. Work as a storage bucket for operations

Also, now the state file will be displaced in the local system, and from now onwards all the operations will we perform be performed on the remote backend. No state file changes will be reflected on the local system.

Go to the backend bucket, and we can see a folder called dev and inside, we can see the adapted state file.

Backend Migration

# Initialize with new backend configuration
terraform init

# Terraform will prompt to migrate existing state
# Answer 'yes' to copy existing state to new backend

# Verify state is now remote
terraform state list

State Commands

# List resources in state
terraform state list

# Show detailed state information
terraform state show <resource_name>

# Remove resource from state (without destroying)
terraform state rm <resource_name>

# Move resource to different state address
terraform state mv <source> <destination>

# Pull current state and display
terraform state pull

Make sure to run the destroy command once you create the backend.

terraform destroy

Arigato!

More from this blog

Code Companions

32 posts