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.
| Aspect | Workspaces | Separate Directories |
|---|---|---|
| Code duplication | None — one codebase | Low if using shared modules |
| Environment isolation | State isolation only | Full isolation (code + state) |
| Risk of prod changes | Higher (same code, wrong workspace) | Lower (different directory) |
| Backend configuration | Shared backend per workspace | Separate backend per environment |
| Complexity | Simple for few environments | Scales 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 NAMEandterraform workspace select NAMEto 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.
