Wednesday, 10 September 2025

Mastering Terraform Workspaces & Environments: Manage Dev, Staging, and Prod with Ease (Part 7)

Standard

In real-world projects, we don’t just have one environment.

We often deal with:

  • Developmentfor experiments and new features
  • Staging a near-production environment for testing
  • Production stable and customer-facing

Manually managing separate Terraform configurations for each environment can get messy.
This is where Terraform Workspaces come in.

What Are Workspaces?

A workspace in Terraform is like a separate sandbox for your infrastructure state.

  • Default workspace = default
  • Each new workspace = a different state file
  • Same Terraform code → Different environments

This means you can run the same code for dev, staging, and prod, but Terraform will keep track of resources separately.

Creating and Switching Workspaces

Commands:

# Create a new workspace
terraform workspace new dev

# List all workspaces
terraform workspace list

# Switch to staging
terraform workspace select staging

Output might look like:

* default
  dev
  staging
  prod

Note: The * shows your current workspace.

Using Workspaces in Code

You can reference the current workspace inside your Terraform files:

resource "aws_s3_bucket" "env_bucket" {
  bucket = "my-bucket-${terraform.workspace}"
  acl    = "private"
}

If you’re in the dev workspace, Terraform creates my-bucket-dev.
In prod, it creates my-bucket-prod.

Case Study: SaaS Company Environments

A SaaS startup had 3 environments:

  • Dev 1 EC2 instance, small database
  • Staging 2 EC2 instances, medium database
  • Prod Auto Scaling group, RDS cluster

Instead of duplicating code, they:

  • Used workspaces for environment isolation.
  • Passed environment-specific variables (dev.tfvars, prod.tfvars).
  • Used the same Terraform codebase for all environments.

Result: Faster deployments, fewer mistakes, and cleaner codebase.

Best Practices for Workspaces

  1. Use workspaces for environments, not for feature branches.
  2. Combine workspaces with variable files (dev.tfvars, staging.tfvars, prod.tfvars).
  3. Keep environment-specific resources in separate state files when complexity grows.
  4. For large orgs, consider separate projects/repos for prod vs non-prod.

Example Project Setup

terraform-project/
  main.tf
  variables.tf
  outputs.tf
  dev.tfvars
  staging.tfvars
  prod.tfvars

Workspace Workflow

  • Select environment: terraform workspace select dev
  • Apply with environment variables: terraform apply -var-file=dev.tfvars

Terraform will deploy resources specifically for that environment.

Advanced Examples with Workspaces

1. Naming Resources per Environment

Workspaces let you build dynamic naming patterns to keep environments isolated:

resource "aws_db_instance" "app_db" {
  identifier = "app-db-${terraform.workspace}"
  engine     = "mysql"
  instance_class = var.db_instance_class
  allocated_storage = 20
}
  • app-db-dev → Small DB for development
  • app-db-staging → Medium DB for staging
  • app-db-prod → High-performance RDS for production

This avoids resource name collisions across environments.

2. Using Workspaces with Remote Backends

Workspaces work especially well when paired with remote state backends like AWS S3 + DynamoDB:

terraform {
  backend "s3" {
    bucket         = "my-terraform-states"
    key            = "env/${terraform.workspace}/terraform.tfstate"
    region         = "us-east-1"
    dynamodb_table = "terraform-locks"
  }
}

Here, each environment automatically gets its own state file path inside the S3 bucket:

  • env/dev/terraform.tfstate
  • env/staging/terraform.tfstate
  • env/prod/terraform.tfstate

This ensures isolation and safety when multiple team members collaborate.

3. CI/CD Pipelines with Workspaces

In modern DevOps, CI/CD tools like GitHub Actions, GitLab CI, or Jenkins integrate with workspaces.

Example with GitHub Actions:

- name: Select Workspace
  run: terraform workspace select ${{ github.ref_name }} || terraform workspace new ${{ github.ref_name }}

- name: Terraform Apply
  run: terraform apply -auto-approve -var-file=${{ github.ref_name }}.tfvars

If the pipeline runs on a staging branch, it will automatically select (or create) the staging workspace and apply the correct variables.

Case Study 1: E-commerce Company

An e-commerce company used to manage separate repos for dev, staging, and prod. This caused:

  • Drift (prod configs didn’t match dev)
  • Duplication (same code copied in three places)

They migrated to one codebase with workspaces:

  • Developers tested features in dev workspace
  • QA validated changes in staging
  • Ops deployed to prod

Impact: Reduced repo sprawl, consistent infrastructure, and easier audits.

Case Study 2: Financial Services Firm

A financial services company needed strict isolation between prod and non-prod environments due to compliance.
They used:

  • Workspaces for logical separation
  • Separate S3 buckets for prod vs non-prod states
  • Access controls (prod state bucket restricted to senior engineers only)

Impact: Compliance achieved without duplicating Terraform code.

Case Study 3: Multi-Region Setup

A startup expanding globally used workspaces per region:

  • us-east-1
  • eu-west-1
  • ap-south-1

Each workspace deployed the same infrastructure stack but in a different AWS region.
This let them scale across regions without rewriting Terraform code.

Pro Tips for Scaling Workspaces

  • Use naming conventions like env-region (e.g., prod-us-east-1) for clarity.
  • Store environment secrets (DB passwords, API keys) in a vault system, not in workspace variables.
  • Monitor your state files—workspace sprawl can happen if you create too many.

What’s Next?

Now you know how to:

  • Create multiple environments with workspaces
  • Use variables to customize each environment
  • Manage dev/staging/prod with a single codebase


Bibliography