# Terraform Workspaces vs Directories: How to Manage Environments

> Compare Terraform and OpenTofu workspaces with separate directories and tfvars files to manage dev, pre and pro environments, and learn which one to use.

- Source: https://www.itwonderlab.com/terraform-workspaces-vs-directories/
- Published: 2026-06-07
- Updated: 2026-06-07
- Author: Javier Ruiz Jiménez (https://www.javierruizjimenez.com/)
- Site: IT Wonder Lab (https://www.itwonderlab.com/)

---

## 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](https://www.itwonderlab.com/terraform-state/); what changes is where the differences live.

### Option 1: Workspaces

A [workspace](https://www.itwonderlab.com/terraform-workspace/) is a named state inside the same [backend](https://www.itwonderlab.com/terraform-backend/). The code is the same and the workspace name is available as `terraform.workspace`.

```shell
$ tofu workspace new dev
$ tofu workspace new pro
$ tofu workspace select dev
$ tofu workspace list
```

```hcl title="main.tf"
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](https://www.itwonderlab.com/terraform-module/).

**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](https://www.itwonderlab.com/terragrunt-opentofu/) removes most of that repetition.

### Option 3: Same directory with tfvars and a backend per environment

```shell
$ 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](https://www.itwonderlab.com/terraform-github-actions-aws-oidc/).

### 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](https://www.itwonderlab.com/best-practices/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.

> [!NOTE]
> Terraform Cloud and HCP Terraform use the word *workspace* for something different: an independent unit with its own state, variables and permissions. It is closer to option 2 than to the CLI workspaces described here.

See also [project structure](https://www.itwonderlab.com/terraform-project-structure/).
