Cloud  /  Terraform

IaC Terraform 50 guides · updated 2026

Infrastructure as code done right — providers, state, reusable modules, and the workflow patterns that keep multi-cloud deployments sane in 2026.

Workspaces in Terraform

Workspaces let you maintain multiple distinct state files within a single backend configuration. The classic use case is managing dev, staging, and production environments from a single set of .tf files. Each workspace has its own state, so changes in one don’t affect the others.


Workspace Basics

Terminal window
# List workspaces (default workspace always exists)
terraform workspace list
# * default
# Create a new workspace
terraform workspace new production
# Switch to an existing workspace
terraform workspace select staging
# Show the current workspace
terraform workspace show
# Delete a workspace (must not be current, must be empty)
terraform workspace delete dev

How Workspaces Affect State Storage

With the S3 backend, workspaces create separate state file paths:

mycompany-terraform-state/
├── production/terraform.tfstate ← default workspace
└── env:/
├── staging/production/terraform.tfstate
└── dev/production/terraform.tfstate

With Terraform Cloud, each workspace is a fully separate entity with its own variables, state, and run history.


Using terraform.workspace in Configuration

The terraform.workspace expression returns the current workspace name:

# Vary resource configuration per workspace
locals {
env = terraform.workspace
instance_type = {
default = "t3.micro"
staging = "t3.small"
production = "t3.large"
}
instance_count = {
default = 1
staging = 2
production = 5
}
}
resource "aws_instance" "app" {
instance_type = local.instance_type[local.env]
count = local.instance_count[local.env]
tags = {
Environment = terraform.workspace
Name = "app-${terraform.workspace}-${count.index + 1}"
}
}
resource "aws_db_instance" "main" {
instance_class = local.env == "production" ? "db.r6g.large" : "db.t3.micro"
multi_az = local.env == "production"
deletion_protection = local.env == "production"
identifier = "myapp-${terraform.workspace}"
}

Workspace-Specific tfvars

Combine workspaces with environment-specific tfvars:

Terminal window
# Apply with workspace-specific variable file
terraform workspace select production
terraform apply -var-file="envs/${terraform.workspace}.tfvars"
# Or use a script to handle the workflow
deploy() {
local env=$1
terraform workspace select "$env" || terraform workspace new "$env"
terraform plan -var-file="envs/${env}.tfvars" -out="${env}.tfplan"
terraform apply "${env}.tfplan"
}
deploy production
envs/production.tfvars
instance_type = "t3.large"
instance_count = 5
enable_ha = true
# envs/staging.tfvars
instance_type = "t3.small"
instance_count = 2
enable_ha = false

TF_WORKSPACE Environment Variable

Set the workspace without running terraform workspace select:

Terminal window
# Use in CI/CD
export TF_WORKSPACE=production
terraform plan # Uses production workspace automatically
# GitHub Actions
- name: Terraform Plan
env:
TF_WORKSPACE: ${{ github.ref == 'refs/heads/main' && 'production' || 'staging' }}
run: terraform plan

Workspace Limitations

Workspaces share the same backend configuration and provider configuration. They’re a state isolation mechanism, not a full environment isolation mechanism.

Limitations:


When to Use Directories Instead

Workspaces work best for environments that are structurally identical with minor configuration differences. For larger teams or significant environment differences, separate directories are often clearer:

infrastructure/
├── environments/
│ ├── dev/
│ │ ├── main.tf ← calls shared modules
│ │ ├── variables.tf
│ │ └── terraform.tfvars
│ ├── staging/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── terraform.tfvars
│ └── production/
│ ├── main.tf
│ ├── variables.tf
│ └── terraform.tfvars
└── modules/
├── networking/
└── application/

Use workspaces when:

Use separate directories when: