# Workspaces

In Terraform, a [workspace](https://developer.hashicorp.com/terraform/language/state/workspaces) is a feature that allows
you to manage multiple "state" environments within a Terraform configuration. Each workspace maintains its own state,
allowing you to deploy and manage infrastructure configurations independently.

Workspaces are useful in several scenarios:

- **Environment Isolation**: Workspaces enable you to have separate environments within a Terraform configuration.
  Each workspace can have its own set of resources and configurations.

- **Parallel Development**: Workspaces facilitate parallel development by allowing different team members to work on
  different workspaces concurrently without interfering with each other's changes.

- **Testing and Experimentation**: Workspaces are helpful for testing and experimentation.
  You can create temporary workspaces to test changes or new configurations without affecting the main production environment.

- **State Management**: Workspaces manage separate states for each environment.
  This helps in maintaining clarity and avoiding conflicts when multiple environments are being managed.

- **Deployment Strategies**: Workspaces can be used to implement different deployment strategies.
  For example, you might use separate workspaces for blue-green deployments or canary releases.

To work with workspaces in Terraform, you can use commands like `terraform workspace new`, `terraform workspace select`,
and `terraform workspace delete` to create, switch between, and delete workspaces respectively.
Atmos automatically manages Terraform workspaces for you when you provision components in a stack.

## Terraform Workspaces in Atmos

Atmos automatically calculates Terraform workspace names and uses workspaces to manage top-level stacks. By default, Atmos uses the stack
name as the Terraform workspace when provisioning components in the stack. For example, consider the following manifest
for the component `vpc` in the stack `ue2-dev`:

**File:** `stacks/ue2-dev.yaml`

```yaml
vars:
  # Context variables that define the Atmos stack `ue2-dev`
  environment: ue2
  stage: dev

components:
  terraform:
    vpc:
      metadata:
        # Point to the Terraform component in `components/terraform/vpc`
        component: vpc
      # Define the variables specific to this component
      vars:
        name: my-vpc
        ipv4_primary_cidr_block: 10.9.0.0/18
```

When you provision the `vpc` component in the stack `ue2-dev` by executing the following command:

```shell
atmos terraform apply vpc -s ue2-dev
```

Atmos computes the workspace name to be `ue2-dev`. Any Atmos Terraform command other than `init`, using this stack,
will cause Atmos to select this workspace, creating it if needed. (This leaves the workspace selected as a side effect
for subsequent Terraform commands run outside of Atmos. Atmos version 1.55 took away this side effect, but it was
restored in version 1.69.)

The exception to the default rule (using the stack name as Terraform workspace) is when we provision more than one
instance of the same Terraform component (with the same or different settings) into the same stack by defining multiple
Atmos components. In this case, Atmos calculates the Terraform workspace for each component by joining the stack name
with the component name.

For example, the following manifest shows how to define two Atmos components, `vpc/1` and `vpc/2`,
which both point to the same Terraform component `vpc`, in the stack `ue2-dev`:

**File:** `stacks/ue2-dev.yaml`

```yaml
vars:
  # Context variables that define the Atmos stack `ue2-dev`
  environment: ue2
  stage: dev

components:
  terraform:
    # Atmos component `vpc/1`
    vpc/1:
      metadata:
        # Point to the Terraform component in `components/terraform/vpc`
        component: vpc
        # Inherit the defaults for all VPC components
        inherits:
          - vpc/defaults
      # Define/override variables specific to this `vpc/1` component
      vars:
        name: vpc-1
        ipv4_primary_cidr_block: 10.9.0.0/18

    # Atmos component `vpc/2`
    vpc/2:
      metadata:
        # Point to the Terraform component in `components/terraform/vpc`
        component: vpc
        # Inherit the defaults for all VPC components
        inherits:
          - vpc/defaults
      # Define/override variables specific to this `vpc/2` component
      vars:
        name: vpc-2
        ipv4_primary_cidr_block: 10.10.0.0/18
```

When you provision the components by executing the commands:

```shell
atmos terraform apply vpc/1 -s ue2-dev
atmos terraform apply vpc/2 -s ue2-dev
```

Atmos computes the workspace names as `ue2-dev-vpc-1` and `ue2-dev-vpc-2` respectively,
and selects the appropriate workspace for each component (again, creating it if needed).
This is done because the same Terraform component `vpc` is used as the workspace prefix
(in case of [AWS S3 backend](https://developer.hashicorp.com/terraform/language/settings/backends/s3),
folder in the S3 state bucket), and it's necessary to have different subfolders (`ue2-dev-vpc-1`
and `ue2-dev-vpc-2` instead of just `ue2-dev`) to store the Terraform state files.

## Terraform Workspace Override in Atmos

You can override Terraform workspaces for Atmos components by using `metadata.terraform_workspace` and
`metadata.terraform_workspace_pattern` attributes. For example:

**File:** `stacks/ue2-dev.yaml`

```yaml
vars:
  environment: ue2
  stage: dev

components:
  terraform:
    vpc/1:
      metadata:
        component: vpc
        # Override Terraform workspace
        terraform_workspace: "vpc-1-workspace-override"

    vpc/2:
      metadata:
        component: vpc
        # Override Terraform workspace
        terraform_workspace_pattern: "{environment}-{stage}-{component}-workspace-override"
```

When you provision the components by executing the commands:

```shell
atmos terraform apply vpc/1 -s ue2-dev
atmos terraform apply vpc/2 -s ue2-dev
```

Atmos sets the Terraform workspace `vpc-1-workspace-override` for the `vpc/1` component, and
`ue2-dev-vpc-2-workspace-override` for the `vpc/2` component.

The following context tokens are supported by the `metadata.terraform_workspace_pattern` attribute:

- `{namespace}`
- `{tenant}`
- `{environment}`
- `{region}`
- `{stage}`
- `{attributes}`
- `{component}`
- `{base-component}`

:::tip
For more information on Atmos base and derived components, and to understand the `{base-component}` token,
refer to [Atmos Component Inheritance](/howto/inheritance)
:::

### Using Go Templates for Workspace Names

_Advanced_

For more complex workspace naming requirements, use `metadata.terraform_workspace_template` which supports full [Go template](https://pkg.go.dev/text/template) syntax with access to [Sprig functions](http://masterminds.github.io/sprig/), [Gomplate functions](https://docs.gomplate.ca/functions/), and [Atmos template functions](/templates).

**File:** `stacks/ue2-dev.yaml`

```yaml
vars:
  environment: ue2
  stage: dev
  custom_suffix: "alpha"

components:
  terraform:
    vpc/3:
      metadata:
        component: vpc
        # Use Go template for dynamic workspace name
        terraform_workspace_template: "{{ .vars.environment }}-{{ .vars.stage }}-{{ .vars.custom_suffix | upper }}"
```

When you provision the component:

```shell
atmos terraform apply vpc/3 -s ue2-dev
```

Atmos evaluates the template and sets the Terraform workspace to `ue2-dev-ALPHA`.

**Priority order for workspace configuration:**

1. `metadata.terraform_workspace_template` (highest) - Full Go template syntax
2. `metadata.terraform_workspace_pattern` - Limited token replacement
3. `metadata.terraform_workspace` - Static string
4. Auto-generated from stack context (lowest) - Default behavior

:::tip When to Use Templates vs. Patterns

- **Use `terraform_workspace_template`** when you need:
  - String manipulation (upper/lower case, substring, etc.).
  - Conditional logic.
  - Access to Sprig/Gomplate functions.
  - Complex naming rules.

- **Use `terraform_workspace_pattern`** when you need:
  - Simple token replacement with context variables.
  - Straightforward naming patterns.

- **Use `terraform_workspace`** when you need:
  - A fixed, static workspace name.
    :::

## How Workspaces Relate to State Paths

Terraform [workspaces](https://developer.hashicorp.com/terraform/cli/workspaces) work together with [backend configuration](https://developer.hashicorp.com/terraform/language/backend/s3) to determine where state files are stored. For remote backends like S3, state files are organized in a two-level hierarchy:

```
s3://bucket/
  └── {workspace_key_prefix}/      # Component identity (e.g., "vpc")
      └── {workspace}/             # Stack context (e.g., "ue2-dev")
          └── terraform.tfstate
```

:::note Workspace Name vs Workspace Key Prefix
These are two separate, independent Terraform concepts that work together to create the full state path:

- **Workspace Name** (`{workspace}` in path): The [Terraform workspace](https://developer.hashicorp.com/terraform/cli/workspaces) name, controlled by:
  - `terraform_workspace_template` (Go templates - full power)
  - `terraform_workspace_pattern` (limited token replacement)
  - `terraform_workspace` (static string)
  - Auto-generated from stack context (default)

- **Workspace Key Prefix** (`{workspace_key_prefix}` in path): The S3 backend's [`workspace_key_prefix`](https://developer.hashicorp.com/terraform/language/backend/s3#workspace_key_prefix) parameter for organizing state files, controlled by:
  - Explicit backend config (`backend.s3.workspace_key_prefix`)
  - `metadata.name` (recommended - stable logical identity)
  - `metadata.component` (physical path)
  - Atmos component name (default)

Each serves a different purpose in organizing your Terraform state. See the official Terraform documentation for [workspaces](https://developer.hashicorp.com/terraform/language/state/workspaces) and [S3 backend configuration](https://developer.hashicorp.com/terraform/language/backend/s3).
:::

- **workspace\_key\_prefix**: Groups all deployments of a component together. Your VPC in dev, staging, and prod all share the same prefix.
- **workspace**: The Terraform workspace name (derived from the stack) that keeps each environment's state separate.

### workspace\_key\_prefix Auto-Generation

Atmos auto-generates `workspace_key_prefix` (for S3), `prefix` (for GCS), or `key` (for Azure) using this priority:

1. Explicit backend config (e.g., `backend.s3.workspace_key_prefix`)
2. `metadata.name` (logical component name)
3. `metadata.component` (physical path to Terraform code)
4. Atmos component name (YAML key)

### Using metadata.name for Stable State Paths

When using [versioned component folders](/design-patterns/version-management/folder-based-versioning), set `metadata.name` to declare the logical component name. This prevents version information from leaking into state paths:

**File:** `stacks/catalog/vpc.yaml`

```yaml
components:
  terraform:
    vpc/defaults:
      metadata:
        type: abstract
        name: vpc           # Logical name (excludes version)
        component: vpc/v2   # Physical path (includes version)
```

With this configuration:

- `workspace_key_prefix` is auto-generated as `vpc` (from `metadata.name`)
- Upgrading to `vpc/v3` only requires changing `metadata.component`
- State path remains `vpc/{workspace}/terraform.tfstate`—no migration needed

:::tip
For more details on versioned components and state management, see [Folder-Based Versioning](/design-patterns/version-management/folder-based-versioning).
:::

## References

- [Component Metadata](/stacks/components/component-metadata) - Configure `terraform_workspace` and `terraform_workspace_pattern`
- [Terraform Workspaces](https://developer.hashicorp.com/terraform/language/state/workspaces)
- [Managing Terraform Workspaces](https://developer.hashicorp.com/terraform/cli/workspaces)
- [Terraform Environment Variables](https://developer.hashicorp.com/terraform/cli/config/environment-variables)
- [Terraform Backends](/components/terraform/backends)

## Disabling Terraform Workspaces

In some cases, you may want to disable Terraform workspaces entirely, particularly when using backends that don't support workspaces. By default, Atmos automatically manages workspaces for supported backend types, but you can control this behavior using the `components.terraform.workspaces_enabled` configuration in your `atmos.yaml` file.

### HTTP Backend and Workspace Support

The [Terraform HTTP backend](https://developer.hashicorp.com/terraform/language/settings/backends/http) does not support workspaces. When Atmos detects that you're using an HTTP backend, it automatically disables workspaces for the affected components, regardless of other configuration settings. This ensures compatibility with HTTP backends while still allowing you to use the same configuration for other backend types.

For example, when you execute a Terraform command with an HTTP backend:

```shell
atmos terraform apply vpc -s ue2-dev
```

Atmos will execute Terraform without attempting to create or select a workspace, using the default workspace instead.

### Explicitly Disabling Workspaces

If you need to disable workspaces for all components, regardless of backend type, you can set the `workspaces_enabled` configuration option in your `atmos.yaml` file:

**File:** `atmos.yaml`

```yaml
components:
  terraform:
    # Disable workspaces for all Terraform components
    workspaces_enabled: false
    # Other Terraform configuration...
```

When workspaces are disabled:

- Atmos will not attempt to create or select workspaces before running Terraform commands
- All Terraform operations will use the default workspace
- Workspace-related variables will be empty in component configurations

:::note
Setting `workspaces_enabled: true` for an HTTP backend will be ignored with a warning message since HTTP backends don't support workspaces.
:::

### When to Disable Workspaces

Consider disabling workspaces in the following scenarios:

- When using backends that don't support workspaces (e.g., HTTP backend)
- When you need consistent behavior with other tools that don't manage workspaces
- When you prefer to manage state files without workspace isolation
- When your workflow already handles environment separation through other means

By properly configuring workspace support, you can ensure that Atmos works seamlessly with all backend types while maintaining the flexibility to adapt to different deployment strategies.
