Explore how Terramate can uplift your IaC projects with a free trial or personalized demo.
Terramate Environments let you manage multiple Terraform and OpenTofu environments without duplicating code, without brittle copy-paste workflows, and with built-in environment promotion as a first-class capability.
Why does it matter
When you’re managing multiple environments in Terraform or OpenTofu, every existing pattern comes with friction.
Workspaces are simple and built-in, but they assume your environments are structurally identical, which limits how much they can evolve independently.
Directory-based setups offer full flexibility but come with code duplication, drift risk, and copy-paste maintenance.
Other strategies, such as branches, tfvars files, Terragrunt, and partial backend configuration, each introduce their own operational overhead and trade-offs.
But they all share the same fundamental gap: there’s no first-class concept of environment promotion, meaning there is no built-in way to confidently move infrastructure changes from dev → staging → production with clear lineage, consistency, and control.
That’s what Terramate Environments unlock: environment promotion for Terraform and OpenTofu, designed to make change progression explicit, repeatable, and production-safe.
How it works
Terramate Environments let platform teams define delivery stages like dev , stg , and prd globally, then use those stages across Terramate Bundles to generate environment-specific infrastructure, manage per-environment configuration overrides, and promote changes through a defined promotion chain.
Watch this 5-minute demo to see how environments work in Terramate:
Create a new Bundle
As the core of managing environments in Terramate are Bundles, which allow users to standardize how infrastructure code is created and structured for environments. In a nutshell, Bundles standardize:
- Where IaC lives in a repository by enforcing paths
- Where the state is managed (e.g., local state, S3, GCS, etc.)
- What provider and Terraform versions should be used.
- What input variables should be exposed to the user when creating a new instance of a Bundle. This is important as end-users can create new instances via a CLI interface and without knowing any Terraform details, meaning it unlocks self-service capabilities.
For this post, we will be using an S3 bucket Bundle from the Catalyst example repo.
Define stages
Take a look at the reference configuration below:
environment {
id = "dev"
name = "Development"
description = "Development Environment"
# promote_from = null # default, cannot be promoted to
}
environment {
id = "stg"
name = "Staging"
description = "Pre-Production Environment: Staging"
promote_from = "dev"
}
environment {
id = "prd"
name = "Production"
description = "Production Environment"
promote_from = "stg"
}Each stage is a first-class object with its own ID, name, and description - making your delivery pipeline explicit, structured, and easy to reason about.
You also define the upstream environment a stage promotes from. That means promotion paths aren’t implicit conventions — they’re encoded in your configuration. As your delivery process evolves, you can introduce new stages and extend your promotion flow without refactoring your entire setup.
Create a new environment from a Bundle
Stages can be used in Terramate Bundle instantiations, to define to which environments Bundle instantiations should be rolled out to.
apiVersion: terramate.io/cli/v1
kind: BundleInstance
metadata:
name: my-bucket
uuid: 6586fa6a-d25a-4d16-9950-d79c226add76
spec:
source: /bundles/acme.com/tf-aws-s3/v1
inputs:
name: my-bucket
visibility: private
terraform_modules:
terraform-aws-modules/s3-bucket/aws:
source: terraform-aws-modules/s3-bucket/aws
version: 5.9.1
environments:
dev: {}Promote dev to stg
To deploy a stg environment for the same Bundle, all it takes is adding the additional state to the YAML configuration.
apiVersion: terramate.io/cli/v1
kind: BundleInstance
metadata:
name: my-bucket
uuid: 6586fa6a-d25a-4d16-9950-d79c226add76
spec:
source: /bundles/acme.com/tf-aws-s3/v1
inputs:
name: my-bucket
visibility: private
terraform_modules:
terraform-aws-modules/s3-bucket/aws:
source: terraform-aws-modules/s3-bucket/aws
version: 5.9.1
environments:
dev: {}
stg: {}In the example above, the configuration in dev and stg will be the same, as none of the inputs have been overwritten. Running terramate generate will then generate the Terraform required not only for the dev but also for the stg environment, following the directory conventions configuration in a Bundle.
Overwrite environment-specific configuration
To overwrite specific configuration for an environment, you can easily overwrite inputs for a specific stage.
apiVersion: terramate.io/cli/v1
kind: BundleInstance
metadata:
name: my-bucket
uuid: 6586fa6a-d25a-4d16-9950-d79c226add76
spec:
source: /bundles/acme.com/tf-aws-s3/v1
inputs:
name: my-bucket
visibility: private
terraform_modules:
terraform-aws-modules/s3-bucket/aws:
source: terraform-aws-modules/s3-bucket/aws
version: 5.9.1
environments:
dev: {}
stg:
inputs:
visibility: public-readIn this configuration, the bucket in dev will have a visibility of private, but in stg, it will be public-read since we explicitly set it.
This now allows us to generate the required infrastructure code as follows:
- dev:
env/dev/s3-buckets/my-bucketmain.tfterraform.tf- …
- stg:
env/stg/s3-buckets/my-bucketmain.tfterraform.tf- …
Again, both can be generated with Terramate using the terramate generate command.
Overwrite dependencies
In some cases, you want to upgrade dependencies, such as the underlying Terraform module version, in specific environments first.
The following example shows how we upgrade the S3 module in dev to version 6.0.0 but in all other environments, it will default to 5.9.1
apiVersion: terramate.io/cli/v1
kind: BundleInstance
metadata:
name: my-bucket
uuid: 6586fa6a-d25a-4d16-9950-d79c226add76
spec:
source: /bundles/acme.com/tf-aws-s3/v1
inputs:
name: my-bucket
visibility: private
terraform_modules:
terraform-aws-modules/s3-bucket/aws:
source: terraform-aws-modules/s3-bucket/aws
version: 5.9.1
environments:
dev:
inputs:
terraform_modules:
terraform-aws-modules/s3-bucket/aws:
source: terraform-aws-modules/s3-bucket/aws
version: 6.0.0
stg:
inputs:
visibility: public-read
prd: {}This means we can also easily update dependencies in specific environments and test before rolling them out to all stages.
Start building
Terramate Environments are open-source and provide a new approach that offers a simple DX, lots of flexibility, and an elegant way to promote environments.
To get started with environments in Terramate, see the following resources:
)
)
)
)