Multi-Environment Layout: Workspaces vs Directory Isolation
Useful for short-lived feature branch environments and identical testing stacks.
Isolates state files and IAM credentials completely between dev, staging, and prod.
Prevents dev experiments from corrupting production state locks or destroying databases.
The Big Idea
How do you manage development, staging, and production environments using Terraform? The official tooling provides a feature called Terraform Workspaces (terraform workspace select prod). While workspaces sound convenient, they have significant architectural limitations in production.
Workspaces share the exact same backend configuration and code. If an engineer forgets which workspace is currently active and runs terraform destroy, they can accidentally vaporize production. Furthermore, workspaces cannot use separate AWS accounts or credential boundaries easily.
The enterprise industry standard is Directory-Based Environment Isolation. You build reusable modules in a shared folder, and create dedicated directories for each environment (environments/dev, environments/prod). Each environment has its own isolated state file, its own distinct backend S3 key, and its own IAM permission boundary, providing zero-blast-radius safety.
Jargon Buster: Plain-English Translations
- Terraform Workspaces: A feature that allows multiple state files to share a single configuration directory.
- Directory Isolation: Structuring projects with separate root directories for each environment to physically isolate state and credentials.
- Blast Radius: The maximum scope of damage that can occur if a catastrophic error, bug, or unauthorized command executes.
- Terragrunt: A popular open-source thin wrapper that helps keep directory-isolated configurations DRY.
Enterprise Directory-Based Environment Architecture
repo-root/
├── modules/ # Reusable, versioned component modules
│ ├── vpc/
│ ├── ecs-cluster/
│ └── rds-postgres/
│
└── environments/ # Concrete environments with isolated state
├── dev/
│ ├── backend.tf # S3 key: "environments/dev/terraform.tfstate"
│ ├── main.tf # Instantiates modules with small dev sizes
│ └── terraform.tfvars
│
├── staging/
│ ├── backend.tf # S3 key: "environments/staging/terraform.tfstate"
│ ├── main.tf
│ └── terraform.tfvars
│
└── prod/
├── backend.tf # S3 key: "environments/prod/terraform.tfstate"
├── main.tf # Multi-AZ HA sizes, strict deletion protection
└── terraform.tfvars
Beginner Traps & Gotchas
1. Relying on workspaces for separate cloud accounts
The Gotcha: Trying to use workspaces to deploy dev into Account A and prod into Account B, causing credential pollution.
The Fix: Use Directory Isolation. Each environment directory explicitly assumes the correct role or account credentials.
2. Copy-pasting identical resource code across dev and prod directories
The Gotcha: Duplicating 500 lines of resource definitions across environments instead of encapsulating them in a shared module.
The Fix: The environment directories should only contain module calls and environment-specific variable values.