Terraform Workspaces
Learn what Terraform workspaces are, how workspace commands work, how state is separated, and when workspaces are helpful or the wrong environment strategy.
What Are Terraform Workspaces?
Terraform workspaces let you use the same Terraform configuration with multiple separate state instances. The most common reason is to represent different environments such as dev, staging, and prod without duplicating all of your .tf files.
A workspace does not create a new directory or a new configuration. It changes which state Terraform is currently using for the same configuration.
That means one codebase can be applied more than once while keeping each environment's state separate.
This is the basic idea:
- same
.tffiles - different selected workspace
- different state for each workspace
For beginners, workspaces seem like a simple multi-environment solution. They can be useful, but they also have important limitations, so it is worth understanding them carefully.
The Default Workspace
When you initialize a new Terraform working directory, Terraform starts in a workspace named default.
You can see the current workspace with:
terraform workspace show
On a fresh project, the result is typically:
default
If you do nothing else and run terraform apply, Terraform stores the state in the default workspace.
That makes default the baseline state context for the configuration.
Why Workspaces Are Useful
Workspaces can be helpful when you want to reuse the same configuration with different data or naming.
Examples:
- deploy the same small stack to
devandstaging - test a module in an isolated workspace before changing the main state
- create short-lived sandboxes for demos or experiments
- keep parallel states for the same code during training
Because each workspace has its own state, Terraform can distinguish between the resources belonging to one environment and the resources belonging to another.
Terraform Workspace Commands
Terraform provides several CLI commands for managing workspaces.
terraform workspace list
Lists all workspaces in the current backend or local working directory.
terraform workspace list
Example output:
* default
dev
staging
The asterisk marks the currently selected workspace.
terraform workspace show
Shows the currently selected workspace.
terraform workspace show
Useful in scripts, CI/CD, and troubleshooting.
terraform workspace new
Creates a new workspace and usually switches to it.
terraform workspace new dev
After this command, Terraform has a new empty state for the dev workspace.
terraform workspace select
Switches to an existing workspace.
terraform workspace select staging
After selection, future plan and apply operations use that workspace's state.
terraform workspace delete
Deletes a workspace.
terraform workspace delete dev
This command removes the workspace state context, so it should be used carefully. Terraform generally expects the workspace not to contain active managed resources unless they are destroyed or migrated first.
A Typical Workspace Flow
A simple learning workflow might look like this:
terraform init
terraform workspace new dev
terraform apply
terraform workspace new staging
terraform apply
terraform workspace list
terraform workspace select dev
terraform plan
The important idea is that Terraform is reusing the same configuration but with different state files behind the scenes.
Using terraform.workspace in Configuration
Terraform exposes the currently selected workspace through the built-in value terraform.workspace.
This allows workspace-aware naming and logic.
Example:
resource "aws_s3_bucket" "logs" {
bucket = "myapp-${terraform.workspace}-logs"
}
If the current workspace is dev, the bucket name becomes myapp-dev-logs. In prod, it becomes myapp-prod-logs.
This is one of the most common beginner uses of workspaces.
Workspace-Based Conditional Logic
You can also use terraform.workspace in expressions.
Example:
locals {
instance_type = terraform.workspace == "prod" ? "t3.medium" : "t3.micro"
}
Or:
resource "aws_instance" "web" {
count = terraform.workspace == "prod" ? 2 : 1
ami = data.aws_ami.ubuntu.id
instance_type = local.instance_type
}
This allows a single codebase to scale environment size based on the active workspace.
Why this is convenient
For small projects, it is nice to avoid maintaining separate copies of nearly identical code. Workspace-aware expressions help the same configuration adapt to each environment.
Why this can also become risky
If too much conditional logic accumulates, a single configuration may become crowded with environment-specific branches. At that point, workspaces may stop being the simplest solution.
Workspace-Based Variable Files
A practical pattern is to keep one variable file per workspace.
Example naming convention:
dev.tfvars
staging.tfvars
prod.tfvars
In automation, you can pair the selected workspace with a matching variable file.
The concept is often described as using ${terraform.workspace}.tfvars as the naming pattern, even though the file selection itself is done by the CLI command or automation workflow.
Example:
terraform workspace select dev
terraform plan -var-file=dev.tfvars
In CI/CD, scripts often compute the file name from the workspace so the right inputs are loaded for the selected environment.
This is a clean way to separate values such as:
- instance sizes
- subnet IDs
- domain names
- replica counts
Workspaces and State
One of the most important facts about workspaces is this:
Each workspace has its own state file or state namespace.
That means Terraform keeps separate records of managed resources for:
defaultdevstagingprod
and any other workspaces you create.
This separation is what prevents Terraform from confusing dev resources with prod resources when using the same code.
Why separate state matters
Terraform decisions are based on state. If multiple environments shared exactly the same state accidentally, Terraform would not be able to model them independently.
Workspaces solve that by splitting state while reusing code.
Backend behavior
The exact storage behavior depends on the backend. With local state, workspace state is stored locally in different paths. With remote backends, the backend typically stores workspace state in separate logical locations.
The details vary, but the high-level idea remains the same: each workspace has its own isolated state context.
Limitations of Workspaces
This is where many beginner misunderstandings happen.
Terraform workspaces are useful, but they are not a full replacement for separate state design, separate backends, or separate repositories in every situation.
Limitation 1: Same configuration for all workspaces
Workspaces assume a mostly shared configuration. If environments differ dramatically, the configuration can become filled with conditionals and exceptions.
Limitation 2: Same backend context
Workspaces usually separate state within the same backend configuration. Some organizations want stronger isolation, separate credentials, or separate backend stores per environment.
Limitation 3: Operational safety
If an operator selects the wrong workspace and runs apply, changes may hit the wrong environment. That risk becomes more serious in production.
Limitation 4: Not always a good fit for large organizations
Large systems often prefer dedicated state, separate pipelines, separate directories, or separate repositories for stronger boundaries between environments.
Workspaces vs Separate Directories or Repositories
This is a common architecture decision.
Workspaces approach
- one codebase
- one backend configuration pattern
- multiple state contexts
- less duplication
- easier for small and similar environments
Separate directories approach
- each environment has its own root module directory
- different backend configuration can be explicit
- environment differences are easier to isolate
- stronger separation, but more structure to maintain
Separate repositories approach
- strongest organizational separation
- often used for strict compliance or team ownership boundaries
- usually more overhead
There is no universal answer. The right choice depends on team size, risk tolerance, environment differences, and governance requirements.
When to Use Workspaces
Workspaces are a good fit when:
- the environments are very similar
- you want lightweight state separation
- the configuration differences are small
- you are learning or prototyping
- you need short-lived sandboxes or demo environments
Examples:
- a tutorial project with dev and staging
- a shared demo stack for training
- a small internal tool with minimal environment drift
When Not to Use Workspaces
Workspaces are usually a weaker fit when:
- production requires strong isolation from non-production
- environments differ substantially
- separate credentials or separate backends are required
- there is a high risk of human error from selecting the wrong workspace
- many teams manage different layers independently
In those cases, separate root modules, directories, or repositories often give clearer operational boundaries.
Practical Example
Here is a small example using terraform.workspace for naming and sizing.
locals {
instance_type = terraform.workspace == "prod" ? "t3.medium" : "t3.micro"
name_prefix = "myapp-${terraform.workspace}"
}
resource "aws_s3_bucket" "logs" {
bucket = "${local.name_prefix}-logs"
}
resource "aws_instance" "web" {
ami = data.aws_ami.ubuntu.id
instance_type = local.instance_type
tags = {
Name = "${local.name_prefix}-web"
}
}
The same configuration behaves differently based on the current workspace while still staying relatively simple.
Best Practices for Using Workspaces Safely
1. Keep environments genuinely similar
If every workspace needs many exceptions, the design may be strained.
2. Make names workspace-aware
Use terraform.workspace in naming to avoid collisions across environments.
3. Pair workspaces with automation
CI/CD should explicitly select the workspace and use the correct variable file rather than relying on manual operator memory.
4. Be cautious with production
If prod deserves stronger isolation, do not assume workspaces alone are enough.
5. Document the environment strategy
Teams should know whether workspaces are the chosen isolation model or just a convenience for non-critical environments.
Common Beginner Mistakes
Mistake 1: Thinking workspaces create separate codebases
They do not. The configuration stays the same; only the state context changes.
Mistake 2: Using workspaces as the answer to every multi-environment problem
Sometimes separate root modules or repos are the better architectural choice.
Mistake 3: Forgetting to include workspace in names
If names do not vary by workspace, you may create collisions in shared accounts.
Mistake 4: Treating workspaces as a complete security boundary
They separate state, but they do not automatically provide all the organizational isolation some environments need.
Final Thoughts
Terraform workspaces are a practical way to reuse one configuration with multiple state instances. They are especially helpful for small, similar environments and learning scenarios where you want dev, staging, and test states without copying directories.
The key ideas to remember are:
- Terraform starts in the
defaultworkspace - workspace commands create, list, select, show, and delete workspace contexts
terraform.workspacelets configuration react to the selected workspace- each workspace has separate state
- workspaces are useful, but they are not a universal environment-management strategy
Use workspaces when they simplify your setup. Avoid them when stronger isolation or significantly different environments demand a more explicit architecture.
Knowledge Check
Question 1: Core Concept
What do Terraform workspaces primarily provide?
Question 2: Built-in Value
What does terraform.workspace represent inside Terraform configuration?
Question 3: Limitations
Why are workspaces not always a replacement for separate directories or repositories?