Selective Terraform Runs in a Monorepo with Terramate
Use Terramate to discover stacks, detect changed directories, and run Terraform or OpenTofu only where needed.
02 Feb 2026, 14:08 UTC

The problem: your CI runs every Terraform root module
In a Terraform monorepo, each directory with its own backend configuration is a root module. A typical CI job loops through every directory and runs terraform plan or terraform apply. When you have dozens of stacks, that wastes minutes on unchanged code, widens the failure surface, and risks applying unrelated changes together in the same pipeline.
The useful takeaway is to keep Terraform or OpenTofu as the execution and state engine, but let Terramate handle stack discovery, Git-based change detection, dependency ordering, and CI invocation. You run commands only on stacks that actually changed, plus any stacks that depend on them.
What a Terramate stack is
A stack is a directory that contains a stack configuration file declaring metadata, tags, and dependencies. Terramate discovers these directories automatically, so you do not maintain a CI matrix by hand. Tags let you group stacks (for example, environment=production), and dependencies express that one stack should be processed after another.
Terramate does not replace Terraform's state backend, locking, provider authentication, or the dependency graph inside a single root module. It orchestrates around those tools.
Because stack configuration file names, command names, and flags have changed between Terramate versions, pin the CLI version in CI and confirm the current names with terramate --help before standardizing them.
Worked example: two stacks and a declared dependency
Imagine a repository with two stacks:
stacks/networking— defines a VPC.stacks/application— defines compute that needs the VPC.
Each directory contains its own Terraform or OpenTofu configuration and a Terramate stack configuration file. In stacks/application, you declare a dependency on stacks/networking so Terramate knows the ordering.
Run this from a local terminal or CI runner with read access to the repository:
# Verify the CLI version you are pinning
terramate --version
# List discovered stacks
terramate list
# Orchestrate a plan-only command across selected stacks.
# Replace the placeholder with the command and flags for your pinned version.
terramate run -- terraform plan -var-file=inputs.tfvars
Expected check: terramate list prints both stack paths. If you modify only stacks/application on a feature branch, change detection should select that stack and, depending on your dependency settings, may also include stacks/networking if the change touches shared outputs. Confirm this behavior on a throwaway branch before relying on it for production applies.
Risk: if stack dependencies are incomplete, Terramate can skip an affected stack or run stacks in the wrong order. Git-based change detection also does not notice out-of-band cloud drift, so it cannot replace drift monitoring.
Trade-offs and limitations
- Added configuration: every stack needs a Terramate config and accurate dependency declarations.
- Version sensitivity: behavior has evolved across releases. Pin the version and validate in CI.
- Concurrency: controlled parallelism can still hit cloud API quotas or cause conflicting changes when stacks share accounts, regions, or quotas.
- No state management: Terramate does not handle state locking or backends; Terraform/OpenTofu still do that.
Practical way to check the result
- Create a tiny repository with two stacks and one declared dependency.
- Run
terramate listand confirm both stacks appear. - Modify one stack on a branch and run the change-detection command for your version. Confirm which stacks are selected and in what order.
- Measure CI duration and executed stack count before and after enabling selective orchestration on representative pull requests.
Closing
Start with one team or one workspace. Pin Terramate, validate terramate list and the orchestration command in CI, and measure the reduction in executed stacks. If the boundaries are clean and dependencies are honest, you get faster, safer runs without replacing Terraform or OpenTofu as your state engine.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.