ENGINEERING NOTES / DEVOPS

Terraform State Management: Kill Local State

Why committing .tfstate to Git is a security disaster. A guide to setting up robust S3+DynamoDB remote backends with encryption and locking.

Terraform State Management: Kill Local State

Author: CloudOpsPro Engineering Team Category: DevOps, IaC, Security Date: December 12, 2025

We still see it in 2025: A terraform.tfstate file committed to a Git repository. This is the DevOps equivalent of storing your credit card number on a sticky note in a public park.

Terraform State is the โ€œbrainโ€ of your infrastructure. If it is lost, corrupted, or exposed, it is Game Over.

1. Why Git Storage is Fatal

  • **Secrets in Plain Text: **Terraform state files store the results of resources. If you create an RDS database and pass a password, that password is stored in plain text in the state file. Commit to Git -> Secrets are compromised forever.
  • **No Locking: **Two engineers run terraform apply at the same time. Git doesnโ€™t prevent this. They overwrite each otherโ€™s changes. Result: Corrupted infrastructure and undefined state.
  • **Manual Errors: **โ€œOops, I forgot to pull before applying.โ€ Now your local state is out of sync with reality.

2. The Solution: Remote Backends with Locking

The extensive standard is S3 + DynamoDB (on AWS).

  • S3 Bucket: Stores the state file (Versioning enabled).
  • DynamoDB Table: Handles the Locking.

Configuration Example

# backend.tf

terraform {
  backend "s3" {
    bucket         = "company-terraform-state-prod"
    key            = "vpc/terraform.tfstate"
    region         = "us-east-1"

    # The Lock Table
    dynamodb_table = "terraform-lock-table"

    # Encryption works by default, but explicit is better
    encrypt        = true
  }
}

Now, when Engineer A runs terraform plan, Terraform writes a Lock ID to DynamoDB. If Engineer B tries to run apply, Terraform checks DynamoDB, sees the lock, and errors out: Error: Error acquiring the state lock.

Safety secured.

3. Best Practices for State Security

Since the state file contains secrets (RDS passwords, IAM keys, TLS private keys):

  1. Encryption at Rest: Ensure the S3 bucket has Server-Side Encryption (SSE-S3 or KMS) enabled.
  2. Access Control: Only the CI/CD role and top-level admins should have s3:GetObject on the state bucket. Developers generally donโ€™t need raw state access; they just need to see the Plan output.
  3. Versioning: Enable S3 Versioning. If a terraform apply corrupts your state file, you can roll back the S3 object to the previous version to recover.

4. Terraform Cloud / Spacelift

If managing S3 backends feels too manual, managed backends like Terraform Cloud or Spacelift are excellent alternatives. They handle:

  • State hosting
  • Locking
  • History/Diffs of state
  • Run triggers

Verdict:

  • Small/Mid Teams: S3 + DynamoDB is fine (and free/cheap).
  • Large Enterprise: Use a managed backend for Audit logs and RBAC.

Whatever you do, add *.tfstate to your .gitignore right now.

A FRESH PERSPECTIVE ON YOUR CLOUD

Great engineering starts
with a good conversation.

Letโ€™s talk about whatโ€™s working, whatโ€™s slowing you down, and what comes next.

Talk to an engineer โ†—