Skip to main content

Command Palette

Search for a command to run...

Day 4 — Terraform State Management & Remote Backend

Updated
7 min read
Day 4 — Terraform State Management & Remote Backend

Today’s learning was all about one of the most important parts of Terraform that many beginners skip at first: state management.
When you start building real AWS infrastructure, understanding the state file and remote backends becomes absolutely essential.

This blog breaks down the concepts in the cleanest and simplest way possible.


🔁 How Terraform Updates Infrastructure

Terraform always tries to make your actual AWS infrastructure match your configuration files.

Here’s the flow every time you run terraform apply:

1️⃣ Reads your Terraform configuration
2️⃣ Reads the state file
3️⃣ Compares the difference
4️⃣ Makes only the required updates

This is why Terraform state is so important — without it, Terraform wouldn’t know what exists.

📌 If it's the first time, how does Terraform read state when there is no state file?

👉 On the very first run (first terraform apply), there is no state file.

So what does Terraform do?

1. Reads your configuration files (.tf files)

It sees what resources you want to create.

❌ 2. State file doesn’t exist yet

Terraform checks for terraform.tfstate.

Since this is the first run, it finds nothing. So Terraform assumes:

“No resources exist yet in real AWS.”

🔄 3. Compares desired vs actual

Desired state = your configuration
Actual state = empty (because no state file)

Terraform concludes:

“All resources need to be created.”

🚀 4. Terraform creates the resources

It creates your VPC, S3 bucket, EC2 instance, etc.

📝 5. Terraform generates the state file

Once resources are created, Terraform stores their details in terraform.tfstate:

  • resource IDs

  • metadata

  • dependencies

  • attributes

  • configuration

Now Terraform knows what exists next time.

🔍 Example

First terraform apply:

  • No state file

  • Terraform thinks: “AWS has nothing.”

  • Creates everything

  • Writes new terraform.tfstate

Second terraform apply:

  • Reads configuration

  • Reads the existing state file

  • Sees what already exists

  • Creates only new resources or updates changes


📄 Terraform State File

Terraform stores all information about your deployed resources inside:

terraform.tfstate

The state file is a JSON file that contains:

  • Resource metadata and current configuration

  • Attributes (CIDR blocks, bucket names, etc.)

  • Provider details

  • Resource dependencies

  • Sensitive data


🛡️ State File Best Practices

To avoid disasters:

✔ Never edit the state file manually
✔ Don’t store it locally for real projects
✔ Use remote state storage (S3)
✔ Enable state locking
✔ Back it up with versioning
✔ Use separate state per environment
✔ Restrict IAM access
✔ Ensure encryption is always ON


☁️ Why Use Remote Backend?

Storing state on S3 gives you:

  • 🔹 Team collaboration

  • 🔹 Secure storage

  • 🔹 Automatic locking

  • 🔹 Versioning & recovery

  • 🔹 High durability


🟦AWS Remote Backend Components

  1. S3 Bucket – stores the Terraform state

  2. S3 Native Locking (Terraform 1.10+) – prevents concurrent changes

  3. IAM policies – control access

No DynamoDB tables. No extra AWS services. Everything happens just with S3.


🔒 S3 Native State Locking

Starting with Terraform 1.10 (released in 2024), you no longer need DynamoDB for state locking. Terraform now supports S3 native state locking using Amazon S3's Conditional Writes feature.

How It Works

  • Terraform tries to create a .tflock file in S3

  • If it exists → lock denied

  • If none exists → apply begins

  • After apply, Terraform deletes lock file (delete marker due to versioning)

Previous Method (DynamoDB):

  • Required separate DynamoDB table creation

  • Additional AWS service to monitor and maintain

  • More complex IAM permissions

  • Extra cost for DynamoDB read/write operations

  • DynamoDB state locking is now discouraged and may be deprecated in future Terraform versions

🏗️ Create an S3 Bucket with Versioning and Encryption Enabled

Before using S3 as a remote backend, you must create a secure bucket to store your Terraform state file.
This bucket should always have versioning and encryption enabled because the state file contains sensitive information.

Example Terraform code:

resource "aws_s3_bucket" "tf_state" {
  bucket = "my-terraform-state-bucket-12345"
}

resource "aws_s3_bucket_versioning" "versioning" {
  bucket = aws_s3_bucket.tf_state.id

  versioning_configuration {
    status = "Enabled"
  }
}

resource "aws_s3_bucket_server_side_encryption_configuration" "encryption" {
  bucket = aws_s3_bucket.tf_state.id

  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm = "AES256"
    }
  }
}

What this does & Why these settings matter:

  • Creates an S3 bucket

  • Enables versioning so every state update is backed up

  • Enables AES256 encryption for security


Initialize Your Backend Using this State File

Once the bucket is ready, you configure Terraform to use it as the backend.

Create a backend.tf file:

terraform {
  backend "s3" {
    bucket       = "my-terraform-state-bucket-12345"
    key          = "dev/terraform.tfstate"
    region       = "us-east-1"
    encrypt      = true
    use_lockfile = true
  }
}

Key Parameters:

  • bucket: S3 bucket name for state storage

  • key: Path within the bucket where 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

⚠️Important: S3 versioning MUST be enabled for S3 native state locking to work properly.

If you keep the bucket-creation file and the backend configuration file in the same folder, you should comment out the backend block before running Terraform. First, create the S3 bucket by applying only the bucket file. Once the bucket is successfully created, uncomment the backend configuration and run terraform init again to enable the remote backend and migrate the state.

Then initialize the backend:

terraform init

Terraform will:

  • Connect to your S3 bucket

  • Create the remote state file

  • Enable state locking (native S3 locking)

  • Ask to migrate your local state (choose yes if prompted)

Objective:

Create an S3 bucket for Terraform remote state, enable versioning + encryption, and then configure Terraform to use S3 as backend.


1. Create S3 Bucket using Terraform (Local Backend First)

📌 s3.tf

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 6.0"
    }
  }
}

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

resource "aws_s3_bucket" "tf_state" {
  bucket = "rajeshreddy-tf-state-bucket"
}

resource "aws_s3_bucket_versioning" "versioning" {
  bucket = aws_s3_bucket.tf_state.id

  versioning_configuration {
    status = "Enabled"
  }
}

resource "aws_s3_bucket_server_side_encryption_configuration" "encryption" {
  bucket = aws_s3_bucket.tf_state.id

  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm = "AES256"
    }
  }
}

2. Initialize Terraform

terraform init

Output:

Terraform has been successfully initialized!

3. Create the S3 Bucket

terraform apply

Enter: yes

Output:

Apply complete! Resources: 3 added, 0 changed, 0 destroyed.

Your remote backend S3 bucket is now created successfully.

4. Configure Remote Backend in Terraform

📌 backend.tf

terraform {
  backend "s3" {
    bucket = "rajeshreddy-tf-state-bucket"
    key    = "global/s3/terraform.tfstate"
    region = "us-east-1"
  }
}

5. Reinitialize Terraform to Migrate State

terraform init

Terraform will ask:

Do you want to copy existing state to the new backend?
Enter a value: yes

Enter yes.

Output:

Successfully configured the backend "s3"!

6. Validate with Terraform Plan

terraform plan

Output:

No changes. Your infrastructure matches the configuration.

This confirms:

  • Backend is working

  • State is stored in S3

  • Terraform is reading it correctly

How to Test State Locking

To verify that S3 native state locking is working:

  1. Terminal 1: Run terraform apply

  2. Terminal 2: While the first is running, try terraform plan or terraform apply

  3. Expected Result: The second command should fail with an error like:

     Error: Error acquiring the state lock
     Error message: operation error S3: PutObject, https response error StatusCode: 412
     Lock Info:
       ID:        <lock-id>
       Path:      <bucket>/<key>
       Operation: OperationTypeApply
       Who:       <user>@<hostname>
    
  4. Check S3 Bucket: During the operation, you'll see a .tflock file temporarily in your S3 bucket

  5. After Completion: The lock file will be automatically deleted (delete marker with versioning)

🧰 Useful State Commands

terraform state list      # list resources
terraform state show res  # show resource details
terraform state rm res    # remove from state
terraform state mv a b    # move resource in state
terraform state pull      # view raw state

Reference Video

This video demonstrates the exact workflow covered in the article. Thanks to piyush sachdeva

More from this blog

B

BejadiRajeshReddy

19 posts