Workspaces & Environments
Isolation is a design decision
Workspaces are per-state runtimes on one backend; environments are the separation of prod/stage/dev. Best practice: separate directories/backends (keys) per env and use workspaces for the rare same-config-different-state case, with per-env variables.
What you will learn
- Distinguish workspaces from environment separation
- Configure per-env tfvars and remote state keys
- Reason about workspace pitfalls in teams
workspace = named state instance over one config. env = prod vs stage vs dev, usually separated by directory + remote backend key + tfvars. Workspaces are convenient; directories are the dependable mainline for state isolation.
What is this?
Workspaces: terraform workspace new <name>; shared configuration, separate state; convenient for small same-shape deployments; limited by inability to vary provider config cleanly and 'workspaces are name-only seams' confusion. Environment separation approaches: directories (envs/prod, envs/stage, envs/dev) each with backend key, tfvars; mono-repo per env with modules; backend per env (per-team). Variables: -var-file, terraform.tfvars.json, *.auto.tfvars, TF_VAR_*. Env-specific knobs: counts conditionals, different SKUs. Gotcha: workspaces + shared resources + provider configs intersect badly across regions; always document the model.
Why do you need it?
- Prod must never see a dev tfvars mistake ride into apply.
- Remote keys per env give clean blast-radius and rollback per stack.
- Per-env variable files are a reviewable boundary between worlds.
- Workspaces misused cause cross-env state collisions hidden until prod breaks.
Mental model
Two kitchens sharing one stove vs two separate kitchens
Workspaces vs env directories
Workspaces = one kitchen, two menus named; fine for small dinners, but grease (configuration) mixes. Separate kitchens (per-env dirs) keep steak night from burning in the pudding.
How it works
- You choose the model before initializing: workspace or dir-key separation.
- Backend key embeds env: envs/prod/site.tfstate vs envs/dev/site.tfstate.
- Each env defines its variable set (tfvars/auto.tfvars) same schema.
- CI applies the correct env only; plan/apply scoped by directory or -workspace.
- Promotion between envs: same code, different vars, tested odd stages.
Environment isolation.
Examples
Per-env backend keys + tfvars
envs/prod/backend.tf → key = "vpc/prod.tfstate"envs/stage/backend.tf → key = "vpc/stage.tfstate"envs/dev/backend.tf → key = "vpc/dev.tfstate" envs/prod/prod.tfvars → env = "prod", instance_type = "m5.large"envs/dev/dev.tfvars → env = "dev", instance_type = "t3.small"# apply: cd envs/prod && terraform apply -var-file=prod.tfvarsState isolation per env + variable boundaries per env, sharing one module tree — the dependable pattern.
In production
- Mono-repo QA: three env directories each CI-deployable.
- Workspace carve for a single-service shard where one config, N named states is truly correct.
- Multi-team: each team's stack dir with its own backend + IAM role.
Best practices
- Default to directories-per-env + remote keys; reach for workspaces only for identical small shards.
- Name everything with the env (kubernetes clusters, buckets, contexts) to avoid collisions.
- Use .auto.tfvars for default dev; explicit -var-file for prod in CI.
- Lock prod state (narrow IAM) so human `destroy -auto-approve` can't casually nuke it.
- Document the isolation model in the README; newer teammates will guess otherwise.
Common mistakes
- One workspace for everything → prod and dev sharing a config inevitably merge.
- Per-env fork of the module tree → drift factory (update once, forget the third).
- Missing -var-file → tfvars from the wrong environment silently applied.
- Failure to namespace global names in shared accounts → creation conflicts.
Debugging tips
- Resource created in wrong env → check current workspace + backend key; verify with state pull.
- Apply silently skipping a var → verify which tfvars/auto-tfvars were loaded (CLI + cwd).
- Promotion broken → compare module versions/locks across env dirs (drift in pin).
- Workspace list vs backend state → reconcile names, one per logical env.
Interview checkpoint
Quick quiz
The dependable way to isolate envs is:
Workspaces give you: