linuxlab.io
Tutorials▾
  • Linux & networking
    File system, processes, TCP/IP, BGP and OSPF
    →
  • Terraform & IaC
    HCL, state, plan/apply on a LocalStack sandbox
    →
  • Git & GitHub
    Object model, plumbing, branching, GitHub Actions
    →
All tutorials →
PricingAboutSign inCreate account
/
Intro
Lessons
Footer
linuxlab-TutorialsPricingAboutPrivacy & cookies
Copyright © 2026 LinuxLab. All rights reserved.
linuxlab.io
Tutorials▾
  • Linux & networking
    File system, processes, TCP/IP, BGP and OSPF
    →
  • Terraform & IaC
    HCL, state, plan/apply on a LocalStack sandbox
    →
  • Git & GitHub
    Object model, plumbing, branching, GitHub Actions
    →
All tutorials →
PricingAboutSign inCreate account
/
  • Introduction
  • Lessons
  • How it works
  • Knowledge base
  • Cheat sheet
  • Capstone
  • Interview prep
home/terraform/kb/Terraform basics/tf-workspace

kb/core ── Terraform basics ── beginner

terraform workspace: several states in one directory

A workspace is a named slot for a separate state file in one directory of HCL. It is useful for very similar environments with a minimal difference between them. This course does not use it; separate folders are usually the better choice.

view as markdownaka: terraform-workspace, workspaces

What a workspace is

A workspace is a named slot that holds a separate state file. The same HCL config with two workspaces builds two independent infrastructures, one per workspace.

Exactly one workspace is active at any moment. The plan, apply, and destroy commands work only in it.

Every project always has a workspace named default. You cannot delete it.

Commands:

bash
terraform workspace list             # list all workspaces
terraform workspace new staging      # create and switch to it
terraform workspace select staging   # switch to an existing one
terraform workspace show             # print the active workspace name
terraform workspace delete staging   # delete (switch to another workspace first)

Where the state files live

With a local backend (see tf-init-backends), the state of each workspace is kept in a subdirectory of terraform.tfstate.d/:

myproject/
├── main.tf
├── terraform.tfstate                       # default workspace
└── terraform.tfstate.d/
    ├── staging/
    │   └── terraform.tfstate
    └── prod/
        └── terraform.tfstate

With a remote backend (S3, GCS, Terraform Cloud) the workspace becomes a key prefix: env:/staging/myproject and so on.

How to use the workspace name in HCL

It is available through terraform.workspace:

hcl
resource "aws_s3_bucket" "logs" {
  bucket = "logs-${terraform.workspace}-acme"

▸"logs-default-acme", "logs-staging-acme", ...

}

This is handy for naming, but it is also risky: the same configuration can create a different number of resources in different workspaces through count = terraform.workspace == "prod" ? 3 : 1. Without firm discipline, two months later nobody remembers how the prod workspace differs from the staging workspace.

When a workspace makes sense

  • Very similar copies of one and the same thing. Per-PR review environments, ephemeral test stands.
  • When the infrastructure really is identical and the only difference is the resource names.
  • When the team understands that a workspace is just one state per config, not an "isolated account".

When a workspace is an anti-pattern

  • Prod / staging / dev. These environments usually differ in their parameters (instance sizes, load), credentials, and access policies. In a single HCL config it is easy to shoot yourself in the foot: get the terraform.workspace == "prod" variable wrong, and something meant for dev ships to prod. The better solution is a separate directory for each environment, with its own backend and its own state.
  • When you need different access permissions for the state. A workspace in one backend means the same set of credentials for state access. You cannot isolate who can read the prod state and who can read staging.
  • Isolating the blast radius. One broken apply in the prod workspace, with a backend that has no locking, can damage both the state itself and the neighboring workspaces.

This is why the course uses ordinary directories instead of workspaces. A workspace is a working tool for niche scenarios.

Workspaces and the remote/local backend

  • Local backend: the workspace switches a subfolder in terraform.tfstate.d/. Everything is local.
  • S3 backend: the workspace becomes a key prefix.
  • Terraform Cloud: the workspace is a first-class entity with its own UI, RBAC, and run history. Here it really does give you isolation.

In other words, a "workspace" in TF Cloud and a "workspace" in the local CLI are two different concepts that share a name. This confuses a lot of people.

Pitfalls

  • You cannot delete default. If you want things clean, create a new workspace and work in it; default stays empty.
  • workspace delete does not delete resources. It only removes the state. If something is deployed in the workspace, run destroy first and delete after, or you will leave orphaned resources in the cloud.
  • terraform.workspace is available inside HCL only after a select. Through the Terraform Cloud UI there can be a nuance: the workspace is set by the run context, not by the CLI.
  • Environment names do not belong hardcoded in the code. In HCL you almost never want to write if terraform.workspace == "prod". Use a variable like environment = "prod" and ordinary conditional expressions instead.

§ команды

bash
terraform workspace list

All workspaces in the current directory. The asterisk marks the active one.

bash
terraform workspace new staging

Create a new workspace and switch to it.

bash
terraform workspace select default

Switch back to default. If it does not exist, Terraform creates it for you.

bash
terraform workspace show

Just the name of the active workspace. Handy in scripts: `if [[ $(terraform workspace show) == prod ]]; then ...`

bash
terraform workspace delete staging

Delete a workspace. Only one that is empty (no resources in state) and not currently active.

§ см. также

  • tf-initterraform init: the first command in any projectterraform init downloads the provider plugins (AWS, GCP, and so on), creates a lockfile that pins their versions, and prepares the working directory. Without it, neither plan nor apply will run.
  • tf-init-backendsBackends in Terraform: where state livesA backend is where the state file is stored. The default is local, next to your HCL. Remote backends (S3, GCS, Terraform Cloud, http) give you shared access and locking. This course uses only local; remote is covered as an overview.
  • tf-destroyterraform destroy: tear down everything you createddestroy removes every resource described in HCL and recorded in state. It is apply with a minus sign in front of everything. It is essential for learning tasks and ephemeral environments. In production it is a last resort.
  • tf-applyterraform apply: apply a plan to a real cloudapply takes the result of plan and actually calls the cloud API: it creates, changes, and deletes resources. After apply, the state is updated. This is the command that turns money into infrastructure.
Footer
linuxlab-
Copyright © 2026 LinuxLab. All rights reserved.
Tutorials
Pricing
About
Privacy & cookies