CoursesTerraformIntermediate

Workspaces & environments

dev, staging, prod from one codebase.

Intermediate12 min · lesson 8 of 15

Almost every team needs the same infrastructure in several environments — dev, staging, prod — that differ only in size and a few settings. There are two established ways to do this in Terraform, and choosing well matters because the wrong one causes prod outages. The two are workspaces and directory-per-environment, and they make different tradeoffs about isolation.

Workspaces: same code, separate state

Workspaces let one configuration keep multiple independent state files — terraform workspace new staging, and the same code now has a separate state for staging. It is lightweight and good for near-identical, ephemeral environments (a per-branch preview). The catch: all workspaces share the same backend and code, and it is easy to run a command against the wrong workspace and change prod thinking you were in dev, because the only difference is invisible current context.

terminal
$ terraform workspace new staging
$ terraform workspace select staging
$ terraform workspace list
default
* staging # the * is your only clue which env you are about to change
# reference it in code: count = terraform.workspace == "prod" ? 3 : 1

Directory (or Terragrunt) per environment

The more robust pattern for prod is a separate directory per environment — environments/dev, environments/prod — each with its own backend config and its own tfvars, usually calling shared modules for the actual resources. This gives strong isolation: prod has its own state, its own backend, and you must be physically in the prod directory to change it. It is more explicit and a little more repetitive, which tools like Terragrunt exist to DRY up.

layout
modules/ # shared, reusable resource definitions
network/ web/ db/
environments/
dev/
main.tf backend.tf dev.tfvars # dev’s own state + values
prod/
main.tf backend.tf prod.tfvars # prod’s own state + values
# to change prod you must cd into environments/prod — explicit and hard to fat-finger
Do not run prod from a workspace by accident
The classic workspace incident: you meant to apply to dev but were still on the prod workspace, and one command later production is changed. If you use workspaces, make the current one impossible to miss (put it in your shell prompt) and gate prod behind CI, not local runs. For strong prod isolation, prefer directory-per-environment so the environment is a path you cd into, not an invisible piece of context.