Terraform Workspaces Managing Multiple Environments

Deploying the same infrastructure to development, staging, and production environments is one of the most common challenges in infrastructure management. Terraform workspaces provide one approach — keeping multiple state files from the same configuration. This topic explains how workspaces work, where they help, and when a different strategy is better.

What Is a Workspace

A workspace is an isolated state file within the same backend. By default, every Terraform project uses a workspace called default. When you create a new workspace, Terraform creates a separate state file for it — so resources created in one workspace are completely independent from resources in another workspace.

Diagram: One Configuration, Multiple State Files

Same .tf files
     |
     |---> workspace: default   ---> state: s3://bucket/terraform.tfstate
     |---> workspace: dev       ---> state: s3://bucket/env:/dev/terraform.tfstate
     |---> workspace: staging   ---> state: s3://bucket/env:/staging/terraform.tfstate
     |---> workspace: prod      ---> state: s3://bucket/env:/prod/terraform.tfstate

Switching workspaces changes which state file Terraform reads and writes — but the code files remain the same.

Workspace Commands

# List all workspaces
terraform workspace list

# Create a new workspace
terraform workspace new staging

# Switch to a workspace
terraform workspace select staging

# Show the current workspace
terraform workspace show

# Delete a workspace (must be empty — no resources in its state)
terraform workspace delete staging

Using the Workspace Name in Configuration

Inside your configuration, access the current workspace name with terraform.workspace. Use it to make resources different across environments.

locals {
  environment   = terraform.workspace
  instance_type = terraform.workspace == "prod" ? "t3.large" : "t3.micro"

  common_tags = {
    Environment = terraform.workspace
    ManagedBy   = "Terraform"
  }
}

resource "aws_instance" "app" {
  ami           = data.aws_ami.linux.id
  instance_type = local.instance_type

  tags = merge(local.common_tags, {
    Name = "${terraform.workspace}-app-server"
  })
}

In the dev workspace this creates a t3.micro instance named dev-app-server. In the prod workspace it creates a t3.large instance named prod-app-server. The exact same code, different outcomes based on the active workspace.

A Practical Workflow with Workspaces

# Create and deploy to dev
terraform workspace new dev
terraform apply

# Test changes are good, now deploy to staging
terraform workspace new staging
terraform apply

# Promote to production
terraform workspace new prod
terraform apply

Environment-Specific Variables with Workspaces

Combine workspaces with a map variable to set per-environment values cleanly:

variable "instance_sizes" {
  type = map(string)
  default = {
    dev     = "t3.micro"
    staging = "t3.small"
    prod    = "t3.large"
  }
}

resource "aws_instance" "app" {
  ami           = data.aws_ami.linux.id
  instance_type = var.instance_sizes[terraform.workspace]
}

Workspaces vs Separate Directories

Workspaces are not the only way to manage multiple environments. Many teams prefer separate directories — one folder per environment, each with its own backend configuration and .tfvars file. Both approaches work, and both have trade-offs.

AspectWorkspacesSeparate Directories
Code duplicationNone — one codebaseLow if using shared modules
Environment isolationState isolation onlyFull isolation (code + state)
Risk of prod changesHigher (same code, wrong workspace)Lower (different directory)
Backend configurationShared backend per workspaceSeparate backend per environment
ComplexitySimple for few environmentsScales better for many teams

For small teams and simple projects, workspaces are convenient. For large organisations with strict environment isolation requirements, separate directories with shared modules is the more common pattern.

Key Points

  • A workspace is an isolated state file within the same backend — the default workspace is always called default.
  • Use terraform workspace new NAME and terraform workspace select NAME to create and switch between workspaces.
  • Access the current workspace name inside configuration with terraform.workspace.
  • Combine workspaces with map variables to configure different sizes, counts, or names per environment.
  • For teams that need strict isolation between environments, separate directories with shared modules often scale better than workspaces.

Leave a Comment