Terraform Workspaces vs Directories: How to Manage Environments
Several environments, one code base #
Almost every project needs the same infrastructure in several environments (dev, pre, pro). There are three common ways to do it with Terraform or OpenTofu. They all give each environment its own state; what changes is where the differences live.
Option 1: Workspaces #
A workspace is a named state inside the same backend. The code is the same and the workspace name is available as terraform.workspace.
$ tofu workspace new dev
$ tofu workspace new pro
$ tofu workspace select dev
$ tofu workspace list
locals {
config = {
dev = { instance_type = "t3.micro", count = 1 }
pro = { instance_type = "m6i.large", count = 3 }
}
env = local.config[terraform.workspace]
}
resource "aws_instance" "web" {
count = local.env.count
ami = data.aws_ami.ubuntu.id
instance_type = local.env.instance_type
}With the S3 backend, each workspace is saved under env:/<workspace>/<key>.
Pros: no duplicated code, easy to create temporary environments.
Cons: it is easy to run apply in the wrong workspace because nothing in the code or directory shows it. All workspaces share the same backend, credentials and code version, so you cannot promote a change from dev to pro gradually. They are not recommended to separate production from other environments.
Option 2: One directory per environment #
infra/
modules/
network/
app/
environments/
dev/
main.tf # calls the modules with dev values
backend.tf
pro/
main.tf
backend.tf
Each environment has its own backend configuration, its own state and its own variables. Shared code lives in modules.
Pros: explicit, different backends, accounts and permissions per environment, you promote changes by updating the module version used in pro.
Cons: some repeated files (backend.tf, providers.tf). Terragrunt removes most of that repetition.
Option 3: Same directory with tfvars and a backend per environment #
$ tofu init -backend-config=backends/pro.hcl -reconfigure
$ tofu plan -var-file=pro.tfvars
Pros: one copy of the code and separate states and accounts. Cons: you must remember to pass the right pair of files. Automate it in a Makefile or in the CI/CD pipeline.
Which one to use #
| Need | Recommendation |
|---|---|
| Separate AWS accounts for dev and pro | Directories (option 2) or tfvars with a backend per environment (option 3) |
| Short-lived copies (a pull request preview, a test) | Workspaces |
| Small project with identical environments | Any, but prefer explicit |
| Large team | Directories with versioned modules |
The general advice of AWS best practices is to use a separate AWS account per environment, which workspaces cannot give you, because one workspace configuration uses one provider configuration.
See also project structure.