/Terraform Workspaces & Multi-Environment
Concept
Medium

Terraform Workspaces & Multi-Environment

8 min read·workspacesmulti-environmentterraform-workspacestate-isolationenvironment-strategydirectory-per-envterraform-cloud-workspacesterraform-associate

Workspaces give a single Terraform configuration multiple isolated state files — one per workspace. The terraform.workspace expression lets configs branch behavior per environment. The exam tests all workspace commands, state storage paths, the default workspace, and the critical tradeoff: workspaces vs directory-per-environment (separate configs). Terraform Cloud workspaces are a distinct, more powerful concept.


1. What are Workspaces?

Workspaces allow a single Terraform configuration directory to maintain multiple independent state files — one per workspace. Each workspace is a completely isolated state environment; resources in one workspace cannot see or affect resources in another.

Rendering diagram…

Key mental model: Workspaces = same config + different state. Resources are managed independently in each workspace even though the .tf files are identical.


2. All Workspace Commands

bash
1# List all workspaces (* marks the currently active one)
2terraform workspace list
3# Output:
4# * default
5#   dev
6#   staging
7#   prod
8
9# Show current workspace name
10terraform workspace show
11# Output: prod
12
13# Create a new workspace (and switch to it)
14terraform workspace new dev
15terraform workspace new staging
16terraform workspace new prod
17
18# Switch to an existing workspace
19terraform workspace select prod
20terraform workspace select default
21
22# Delete a workspace (must have empty state — no resources)
23terraform workspace delete dev
24
25# Create without switching (Terraform >= 1.1)
26terraform workspace new --no-color uat

Exam tip: terraform workspace new both creates and switches to the new workspace. terraform workspace select only switches.


3. The default Workspace

  • Named defaultalways exists
  • Cannot be deleted
  • State file location: terraform.tfstate (local) or the backend's base key (remote)
  • If you never create other workspaces, you are always in default
bash
1terraform workspace show   # → default
2terraform workspace list   # → * default

4. State File Paths

Workspaces keep state separate by using distinct file paths:

BackendWorkspaceState Path
Localdefaultterraform.tfstate
Localdevterraform.tfstate.d/dev/terraform.tfstate
Localprodterraform.tfstate.d/prod/terraform.tfstate
S3default<key> (e.g., prod/app/terraform.tfstate)
S3devenv:/dev/<key>
S3prodenv:/prod/<key>
Terraform CloudanySeparate workspace = separate state
bash
1# Local state directory structure after creating dev and prod workspaces:
2.
3├── terraform.tfstate           ← default workspace
4├── terraform.tfstate.d/
5│   ├── dev/
6│   │   └── terraform.tfstate  ← dev workspace
7│   └── prod/
8│       └── terraform.tfstate  ← prod workspace

5. Using terraform.workspace in Configuration

The terraform.workspace expression returns the name of the current workspace as a string:

hcl
1# Simple conditional on resource size
2resource "aws_instance" "web" {
3  ami           = data.aws_ami.ubuntu.id
4  instance_type = terraform.workspace == "prod" ? "t3.large" : "t3.micro"
5
6  tags = {
7    Name        = "${terraform.workspace}-web-server"
8    Environment = terraform.workspace
9  }
10}
11
12# Conditional resource count
13resource "aws_instance" "web" {
14  count         = terraform.workspace == "prod" ? 3 : 1
15  instance_type = "t3.micro"
16}
17
18# Using workspace in naming to avoid conflicts
19resource "aws_s3_bucket" "app" {
20  bucket = "my-app-${terraform.workspace}-data"
21  # dev   → my-app-dev-data
22  # prod  → my-app-prod-data
23}

6. Workspace Variable Maps Pattern

A common pattern is a local map keyed by workspace name, which avoids long chains of conditionals:

hcl
1locals {
2  # Define all environment-specific values in one place
3  env_config = {
4    default = {
5      instance_type  = "t3.micro"
6      instance_count = 1
7      db_class       = "db.t3.micro"
8      multi_az       = false
9    }
10    dev = {
11      instance_type  = "t3.micro"
12      instance_count = 1
13      db_class       = "db.t3.micro"
14      multi_az       = false
15    }
16    staging = {
17      instance_type  = "t3.small"
18      instance_count = 2
19      db_class       = "db.t3.small"
20      multi_az       = false
21    }
22    prod = {
23      instance_type  = "t3.medium"
24      instance_count = 4
25      db_class       = "db.t3.medium"
26      multi_az       = true
27    }
28  }
29
30  # Look up current workspace's config (fallback to dev if unknown workspace)
31  config = lookup(local.env_config, terraform.workspace, local.env_config["dev"])
32}
33
34resource "aws_instance" "web" {
35  count         = local.config.instance_count
36  instance_type = local.config.instance_type
37}
38
39resource "aws_db_instance" "main" {
40  instance_class = local.config.db_class
41  multi_az       = local.config.multi_az
42}

This pattern is clean, readable, and scales well as environments grow.


7. Workspaces vs Directory-per-Environment

This is a critical exam topic — know when to use each approach:

Rendering diagram…
AspectWorkspacesDirectory per Environment
Config sharingSame files for all envsSeparate files per env
State isolationFull — separate state fileFull — separate state file
Config isolationNone — one change affects allFull — independent configs
Environment differencesMust use conditionals / local mapsSeparate tfvars or configs
Blast radius of bugAll workspaces share the bugOnly affected env
Refactoring overheadLow — change onceHigh — change in N directories
VisibilityHarder — must know current workspaceClear — directory shows env
Best forTruly identical infra, different sizesInfra that varies significantly
Terraform recommendSimple casesProduction-grade multi-env

When workspaces work well:

  • All environments are structurally identical (only size/count differs)
  • Small teams where shared config is manageable
  • Testing or ephemeral environments (feature branches, PRs)

When directory-per-environment is better:

  • Environments have meaningfully different resources (prod has WAF, dev doesn't)
  • You need separate state backends per environment
  • Strict change control (prod changes must be explicit)
  • Large teams where accidental cross-environment changes are risky

8. CI/CD Workflow with Workspaces

bash
1# Typical CI/CD pipeline using workspaces
2
3# Step 1: Select or create the workspace for this deployment target
4terraform workspace select prod || terraform workspace new prod
5
6# Step 2: Plan with workspace-specific var file
7terraform plan -var-file="environments/prod.tfvars" -out=prod.tfplan
8
9# Step 3: Apply the saved plan
10terraform apply prod.tfplan
11
12# Step 4: Show current workspace in output
13echo "Deployed to workspace: $(terraform workspace show)"
bash
1# Feature branch workflow — ephemeral workspace per PR
2BRANCH_NAME=$(git rev-parse --abbrev-ref HEAD | tr '/' '-')
3terraform workspace new $BRANCH_NAME || terraform workspace select $BRANCH_NAME
4terraform apply -auto-approve
5
6# After PR merge — clean up
7terraform destroy -auto-approve
8terraform workspace select default
9terraform workspace delete $BRANCH_NAME

9. Terraform Cloud Workspaces — Important Distinction

Terraform Cloud workspaces are fundamentally different from CLI workspaces:

AspectCLI WorkspacesTerraform Cloud Workspaces
ScopeState isolation within one configFull execution environment
ConfigShared .tf filesCan have different VCS repos
Variablesterraform.workspace in codePer-workspace variable sets
ExecutionLocal machineRemote execution in TC runners
Access controlFile systemPer-workspace teams/permissions
Recommended forSimple multi-stateAll production use cases

In Terraform Cloud, each workspace is more like a complete deployment environment — with its own:

  • State file
  • Variables and secrets
  • VCS connection (branch/repo)
  • Run history and approval gates
  • Access controls (who can plan vs apply)
hcl
1# Connecting to Terraform Cloud (replaces backend "s3")
2terraform {
3  cloud {
4    organization = "my-company"
5
6    workspaces {
7      name = "production-app"         # single named workspace
8      # OR
9      tags = ["app", "production"]    # all workspaces with these tags
10    }
11  }
12}

10. Multi-Account AWS Pattern

For strict environment isolation, use separate AWS accounts (not just workspaces):

hcl
1# provider.tf — provider per AWS account
2
3# Dev account
4provider "aws" {
5  alias  = "dev"
6  region = "us-east-1"
7  assume_role {
8    role_arn = "arn:aws:iam::111111111111:role/TerraformRole"
9  }
10}
11
12# Prod account
13provider "aws" {
14  alias  = "prod"
15  region = "us-east-1"
16  assume_role {
17    role_arn = "arn:aws:iam::999999999999:role/TerraformRole"
18  }
19}
bash
1# Backend with separate state per account+environment
2# environments/prod/backend.tf
3terraform {
4  backend "s3" {
5    bucket = "prod-account-terraform-state"
6    key    = "app/terraform.tfstate"
7    region = "us-east-1"
8    # This bucket lives in the prod AWS account
9  }
10}

11. Quick Reference

ConceptKey Fact
terraform workspace new XCreates AND switches to workspace X
terraform workspace select XSwitches to existing workspace X
terraform workspace listLists all workspaces; * = current
terraform workspace showPrints current workspace name
terraform workspace delete XDeletes X (must have empty state)
default workspaceAlways exists; cannot be deleted
terraform.workspaceExpression returning current workspace name (string)
Local state pathterraform.tfstate.d/<name>/terraform.tfstate
S3 state pathenv:/<name>/<key> for non-default workspaces
Workspaces isolateState only — config is shared
Workspace best forIdentical infra at different scales
Directory-per-env best forDifferent infra per environment
TC workspaces vs CLITC workspaces = full execution env; CLI = state isolation only

Practice Questions3

easy

Q1. What command creates a new Terraform workspace named `staging` and switches to it?


Select one answer before revealing.

medium

Q2. How can you reference the current Terraform workspace name within your configuration to set different resource sizes per environment?


Select one answer before revealing.

hard

Q3. What is the key limitation of using Terraform workspaces for environment management?


Select one answer before revealing.