Terraform Stacks (GA late 2025) and Workspaces solve different problems, but teams often confuse them. Workspaces isolate state for the same configuration. Stacks orchestrate multiple configurations as a single deployment. Here’s when to use each.
Core Difference in 30 Seconds
Workspaces: One Terraform configuration → multiple isolated state files (dev, staging, prod).
Stacks: Multiple Terraform configurations → one coordinated deployment (networking + database + compute).
Workspaces:
main.tf ──→ dev.tfstate
──→ staging.tfstate
──→ prod.tfstate
Stacks:
networking/main.tf ─┐
database/main.tf ─┼──→ coordinated apply/destroy
compute/main.tf ─┘
Side-by-Side Comparison
| Feature | Workspaces | Stacks |
|---|---|---|
| Purpose | Same code, different environments | Multiple codebases, one deployment |
| State files | One per workspace | One per component |
| Dependencies | Manual (remote_state data) | Declared (component.X.output) |
| Apply order | You decide | Automatic (dependency graph) |
| Destroy order | You decide (reverse) | Automatic |
| Multi-env | terraform workspace select | Deployment targets in .tfdeploy.hcl |
| Requires HCP | No (CLI works) | Yes (HCP Terraform only) |
| OpenTofu | ✅ Supported | ❌ Not available |
| Complexity | Low | Medium |
| Best for | Environment isolation | Multi-component systems |
Workspaces: Environment Isolation
How They Work
# Create workspaces
terraform workspace new dev
terraform workspace new staging
terraform workspace new prod
# Switch and apply
terraform workspace select dev
terraform apply # Uses dev.tfstate
terraform workspace select prod
terraform apply # Uses prod.tfstate (completely separate)
Typical Structure
project/
├── main.tf
├── variables.tf
├── outputs.tf
├── terraform.tfvars # Default values
├── environments/
│ ├── dev.tfvars
│ ├── staging.tfvars
│ └── prod.tfvars
# main.tf — same code for all environments
resource "aws_instance" "web" {
ami = var.ami_id
instance_type = var.instance_type # t3.micro in dev, t3.xlarge in prod
tags = {
Name = "${terraform.workspace}-web"
Environment = terraform.workspace
}
}
terraform workspace select prod
terraform apply -var-file=environments/prod.tfvars
When Workspaces Work Well
- Same architecture, different sizes: Dev gets t3.micro, prod gets t3.xlarge
- Same resources, different accounts: Deploy identical infra to dev/staging/prod AWS accounts
- Feature environments: Spin up temporary environments for testing
- Simple projects: Single root module, no cross-module dependencies
When Workspaces Break Down
# Problem: Networking team manages VPC, app team manages compute
# With workspaces, everything is in one configuration
resource "aws_vpc" "main" { ... } # Networking team
resource "aws_ecs_cluster" "app" { ... } # App team
resource "aws_rds_cluster" "db" { ... } # Database team
# Issues:
# - One team's change can break another's
# - Long plan times (Terraform evaluates everything)
# - Blast radius is the entire stack
# - Different teams need different permissions
Stacks: Multi-Component Orchestration
How They Work
# stack.tfstack.hcl
component "networking" {
source = "./components/networking"
inputs = {
environment = var.environment
vpc_cidr = var.vpc_cidr
}
}
component "database" {
source = "./components/database"
inputs = {
environment = var.environment
vpc_id = component.networking.vpc_id # Auto-dependency
subnet_ids = component.networking.private_subnets
}
}
component "compute" {
source = "./components/compute"
inputs = {
environment = var.environment
vpc_id = component.networking.vpc_id
db_endpoint = component.database.endpoint # Auto-dependency
}
}
# deployments.tfdeploy.hcl
deployment "dev" {
inputs = {
environment = "dev"
vpc_cidr = "10.0.0.0/16"
}
}
deployment "prod" {
inputs = {
environment = "prod"
vpc_cidr = "10.1.0.0/16"
}
}
When Stacks Work Well
- Multi-team projects: Networking, database, and compute teams own separate components
- Complex dependency chains: Database needs VPC, compute needs VPC + database
- Coordinated destroy: Tear down compute → database → networking in correct order
- Large infrastructure: 100+ resources split across logical components
- Deferred changes: Component B can’t plan until Component A creates resources
When Stacks Are Overkill
- Simple single-module projects
- Projects that don’t need cross-component coordination
- Teams not on HCP Terraform
- Projects needing OpenTofu compatibility
The Decision Framework
Q: Do you have ONE Terraform configuration used in multiple environments?
→ Use WORKSPACES
Q: Do you have MULTIPLE Terraform configurations that deploy together?
→ Use STACKS
Q: Do you have both?
→ Use STACKS (they include deployment targets for multi-env)
Real-World Examples
| Scenario | Use |
|---|---|
| Same web app deployed to dev/staging/prod | Workspaces |
| VPC + EKS + RDS deployed as a unit | Stacks |
| Per-developer preview environments | Workspaces |
| Platform team managing shared infra + app teams deploying on top | Stacks |
| Single Lambda function in 3 regions | Workspaces |
| Microservices with shared networking and individual services | Stacks |
Before Stacks: The Workspace + Remote State Pattern
Before Stacks existed, teams used workspaces + terraform_remote_state data sources:
# In the compute configuration:
data "terraform_remote_state" "networking" {
backend = "s3"
config = {
bucket = "tf-state"
key = "networking/terraform.tfstate"
region = "us-east-1"
}
}
resource "aws_ecs_cluster" "app" {
name = "app"
# Reference networking output
# But if networking hasn't been applied yet... this fails
}
resource "aws_ecs_service" "app" {
cluster = aws_ecs_cluster.app.id
network_configuration {
subnets = data.terraform_remote_state.networking.outputs.private_subnets
}
}
Problems with this approach:
- No orchestration — you must apply networking first, manually
- No coordinated destroy
- Remote state references are fragile
- No deferred changes
Stacks solve all of these.
Can You Use Both?
Yes — within a Stack, each component can use workspaces internally. But in practice, Stacks’ deployment targets replace the need for workspaces in most cases.
Hands-On Courses
- Terraform for Beginners on CopyPasteLearn
- Terraform By Example — practical code examples
Conclusion
Workspaces and Stacks solve fundamentally different problems. Use Workspaces when you have one configuration deployed to multiple environments. Use Stacks when you have multiple configurations that need coordinated deployment and destruction. For simple projects, Workspaces are sufficient and work everywhere (CLI, HCP, OpenTofu). For complex multi-component systems on HCP Terraform, Stacks eliminate the manual orchestration and remote state glue that teams have fought with for years.