Day 20: Remote State & Backend Configuration

I'm a cloud-native enthusiast and tech blogger, sharing insights on Kubernetes, AWS, CI/CD, and Linux across my blog and Facebook page. Passionate about modern infrastructure and microservices, I aim to help others understand and leverage cloud-native technologies for scalable, efficient solutions.
Welcome to Day 20 — the final day of Week 3 in our Terraform series!
Today, we’ll dive into one of the most important production concepts in Terraform — remote state backends.
You’ll learn how to safely store, share, and protect Terraform state files in real-world team environments.
🎯 Learning Objectives
By the end of today, you will be able to:
✅ Configure remote backends (S3 or Terraform Cloud)
✅ Enable state locking using DynamoDB
✅ Read data from remote state files
✅ Manage multiple environments using isolated states
✅ Understand state isolation strategies and best practices
🧩 What Is Terraform State?
Terraform keeps track of your infrastructure resources in a file called terraform.tfstate.
This file acts as a record of what resources Terraform manages and their current attributes (like IDs, IPs, etc).
By default, this state is stored locally (on your machine).
That works fine for testing — but it’s risky for real production environments.
⚠️ Problems with Local State
When Terraform state is stored locally, you face several issues:
| Problem | Description |
| ❌ No collaboration | Other team members can’t share or view the same state file |
| ❌ No locking | Two users running Terraform at the same time can corrupt the state |
| ❌ No encryption | Sensitive data like passwords or secrets may be stored in plain text |
| ❌ Risk of loss | If your laptop dies, your state is gone |
| ❌ No versioning | You can’t roll back to a previous state |
✅ Why Use Remote State?
Remote backends solve all of these issues.
When you store your Terraform state remotely (for example, in S3 or Terraform Cloud), you get:
| Benefit | Description |
| ✅ Collaboration | Shared state file accessible by all team members |
| ✅ State Locking | Prevents simultaneous updates |
| ✅ Encryption | Keeps your state file secure |
| ✅ Versioning | Easily roll back to previous versions |
| ✅ Audit Trail | Tracks who changed what and when |
☁️ Remote State with AWS S3 (Recommended)
The most common backend setup for AWS-based projects is S3 + DynamoDB.
S3 stores the state file.
DynamoDB ensures state locking, preventing concurrent writes.
🧱 Basic S3 Backend Example
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "project/terraform.tfstate"
region = "us-east-1"
}
}
🧠 Explanation:
bucket: The name of your S3 bucket that stores state.key: The path (like a folder) inside the bucket for the state file.region: AWS region of the bucket.
🔒 S3 Backend with DynamoDB Locking
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "project/terraform.tfstate"
region = "us-east-1"
encrypt = true
dynamodb_table = "terraform-locks"
workspace_key_prefix = "workspaces"
}
}
🧠 Explanation:
encrypt = true→ Enables server-side encryption (AES-256).dynamodb_table→ Uses DynamoDB to lock the state during apply.workspace_key_prefix→ Keeps separate states for each workspace.
🏗️ Create Backend Infrastructure
Before configuring your backend, you must create the S3 bucket and DynamoDB table to store your state safely.
# backend-setup.tf
data "aws_caller_identity" "current" {}
resource "aws_s3_bucket" "terraform_state" {
bucket = "terraform-state-${data.aws_caller_identity.current.account_id}"
tags = {
Name = "Terraform State"
Environment = "Production"
}
}
resource "aws_s3_bucket_versioning" "terraform_state" {
bucket = aws_s3_bucket.terraform_state.id
versioning_configuration {
status = "Enabled"
}
}
resource "aws_s3_bucket_server_side_encryption_configuration" "terraform_state" {
bucket = aws_s3_bucket.terraform_state.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
resource "aws_s3_bucket_public_access_block" "terraform_state" {
bucket = aws_s3_bucket.terraform_state.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
resource "aws_dynamodb_table" "terraform_locks" {
name = "terraform-state-locks"
billing_mode = "PAY_PER_REQUEST"
hash_key = "LockID"
attribute {
name = "LockID"
type = "S"
}
tags = {
Name = "Terraform State Locks"
Environment = "Production"
}
}
🧠 Explanation:
S3 Bucket: Stores Terraform state.
Versioning: Keeps history of changes to allow rollback.
Encryption: Protects your state file.
Public Access Block: Prevents public exposure.
DynamoDB Table: Manages state lock to prevent concurrent operations.
🔄 Initialize the Remote Backend
Migrating from Local to Remote
# Step 1: Add backend config
terraform {
backend "s3" {
bucket = "bucker-name
key = "prod/terraform.tfstate"
region = "us-east-1"
}
}
# Step 2: Initialize with migration
terraform init -migrate-state
# Step 3: Verify S3 file
aws s3 ls s3://bucket-name/prod/
Reconfiguring Backend
# To change backend settings
terraform init -reconfigure
# To migrate existing state forcefully
terraform init -migrate-state -force-copy
🧠 Backend Configuration Patterns
Terraform gives you multiple ways to provide backend configuration.
🧩 Pattern 1: Partial Configuration (Recommended)
Keep sensitive values outside your code.
terraform {
backend "s3" {}
}
backend-config/prod.hcl
bucket = "prod-terraform-state"
key = "infrastructure/terraform.tfstate"
region = "us-east-1"
encrypt = true
dynamodb_table = "prod-terraform-locks"
Initialize using:
terraform init -backend-config=backend-config/prod.hcl
🧩 Pattern 2: Environment Variables
export TF_CLI_ARGS_init="-backend-config=bucket=my-state-bucket"
terraform init
🧩 Pattern 3: Command Line Arguments
terraform init \
-backend-config="bucket=my-state-bucket" \
-backend-config="key=project/terraform.tfstate" \
-backend-config="region=us-east-1"
🧱 State Isolation Strategies
State isolation ensures different environments (dev, staging, prod) do not interfere with each other.
1️⃣ Directory-Based Isolation
terraform/
├── dev/
│ └── backend.tf # key = "dev/terraform.tfstate"
├── staging/
│ └── backend.tf # key = "staging/terraform.tfstate"
└── prod/
└── backend.tf # key = "prod/terraform.tfstate"
Each environment has its own backend file and state file.
2️⃣ Workspaces
terraform {
backend "s3" {
bucket = "terraform-state"
key = "project.tfstate"
workspace_key_prefix = "env"
region = "us-east-1"
}
}
💡 Workspaces create automatically isolated state files:
s3://terraform-state/env/dev/project.tfstate
s3://terraform-state/env/prod/project.tfstate
terraform workspace new dev
terraform workspace select dev
☁️ Terraform Cloud Backend
Terraform Cloud provides a fully managed remote backend with versioning, state locking, and collaboration out of the box.
Basic Configuration
terraform {
cloud {
organization = "stackop"
workspaces {
name = "dev-workspace"
}
}
}
Using Multiple Workspaces
terraform {
cloud {
organization = "stackops"
workspaces {
tags = ["networking", "production"]
}
}
}
🎉 Summary
By now, you’ve learned how to:
✅ Configure and migrate to remote state
✅ Enable state locking with DynamoDB
✅ Organize environments using isolation strategies
✅ Use Terraform Cloud as an alternative backend
🚀 Day 21 Preview
Day 21: Workspaces for Environment Management
focuses on advanced techniques:
Workspaces
Terraform import
Provisioners
Testing strategies
CI/CD integration
Security best practices
← Day 19: Module Sources | Day 22: Workspaces →
Remember: Remote state is essential for team collaboration and production deployments!


