Speeding Up Terraform CI/CD with Terramate’s Change‑Detection Selective Execution
Learn how Terramate’s change‑detection driven <code>--only-changed</code> flag lets CI run Terraform only on affected stacks, cutting plan/apply time in large monorepos.
01 May 2026, 01:42 UTC

The Problem: Full‑Repo Terraform Runs Waste Time
In a large Terraform monorepo, every commit often triggers a pipeline that runs terraform plan or terraform apply on all stacks, even when only a single stack’s files changed. This leads to long CI cycles, wasted compute minutes, and slower feedback for developers.
How Terramate Detects Changes
Terramate builds a directed acyclic graph (DAG) from each stack’s stack.hcl manifest. The graph captures explicit dependencies (e.g., depends_on) between stacks. When a commit arrives, Terramate walks the DAG starting from any stack whose tracked files (typically .tf, .tfvars, or files listed in stack.hcl) have been modified. The result is a list of stacks that are directly or transitively affected.
The command terramate run --list-changed prints exactly those stacks, without invoking Terraform.
Running Only Changed Stacks in CI
With the list of affected stacks in hand, you can tell Terramate to execute Terraform commands solely on those stacks using the --only-changed flag:
# Run from the repository root (requires read access to the repo and permission to execute terraform)
terramate run --only-changed terraform plan
Terramate will:
- Determine the changed stacks via its internal DAG walk.
- For each stack, change into its directory and run the supplied Terraform command (
planin the example). - Skip stacks that are not in the changed set.
If no files have changed, the tool reports an empty list and skips Terraform entirely.
Worked Example: Updating a Network Stack
Assume a repo with three stacks: network, compute, and database. The compute stack depends on network (declared in its stack.hcl). A developer edits network/variables.tf to add a new subnet.
Running the detection command:
terramate run --list-changed
Expected output (illustrative):
network
compute
Because compute depends on network, it appears as transitively affected. Executing the plan:
terramate run --only-changed terraform plan
Terramate will run terraform plan only in the network and compute directories. The database stack is skipped, saving its plan time.
Trade‑offs and Limitations
Selective execution relies on a complete Git history. If the CI agent checks out a shallow clone (--depth 1) or the .git directory is missing, Terramate may not see the full file‑change set and could either miss affected stacks or incorrectly flag unrelated ones. To avoid this, ensure your CI fetches the full history (git fetch --unshallow or omit --depth).
Another limitation: Terramate only considers changes to files it tracks via the stack manifests. If a stack’s Terraform code generates resources through an external script that writes files outside the tracked paths, those changes won’t trigger a re‑run. You can mitigate this by adding generated files to the files list in stack.hcl or by manually triggering a run when you know such scripts have executed.
Putting It Into Practice
Add the following step to your CI configuration (example for a generic YAML‑based pipeline):
steps:
- checkout: self
fetch-depth: 0 # ensure full history
- script: |
terramate run --list-changed
terramate run --only-changed terraform plan -input=false
After the step runs, inspect the logs: you should see Terraform invoked only for the stacks listed by --list-changed. If you revert the edit and repeat the step, the list will be empty and no Terraform commands will appear, confirming that unchanged work is truly skipped.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.