Using Terramate’s Changed‑Only Flag to Speed Up Terraform Runs
Learn how Terramate’s changed‑only flag limits Terraform execution to stacks with actual file changes, speeding up CI pipelines and reducing risk.
26 Jun 2026, 04:57 UTC

The problem: waiting for unchanged Terraform stacks
In a repository that contains many Terraform stacks, a typical CI pipeline runs terraform plan or terraform apply on every stack for each pull request. Even when only one stack has changed, the pipeline spends minutes processing the rest, which slows feedback and increases the chance of unnecessary changes.
How Terramate’s change‑detection works
Terramate stores a lightweight state file for each stack in a hidden .terramate directory. When you run terramate run terraform --changed-only, it compares the current Git commit with the previous commit (or the commit recorded in .terramate/state) and determines which stacks have had any of their source files (.tf, .vars, referenced modules) modified. Only those stacks are passed to Terraform; the others are skipped entirely.
This mechanism does not inspect Terraform plan output or try to predict downstream effects; it relies solely on file‑level changes in the Git history.
Worked example: applying a change to a single stack
- Clone a Terramate‑enabled repo and ensure you have write permission to the working directory.
- Make a change to a stack’s file, for example edit
stacks/network/main.tf. - Commit the change:
git add stacks/network/main.tf && git commit -m "update network CIDR". - Run the changed‑only command in your CI job or locally:
terramate run terraform apply --changed-only -auto-approve - Observe the output: you should see Terraform planning and applying only for the
networkstack, while other stacks are reported as "skipped" by Terramate. - To verify that the gating is working, delete the
.terramatedirectory (rm -rf .terramate) and run the same command without--changed-only. All stacks should now be processed, confirming that the state directory drives the detection.
No output is invented here; you will see the actual Terraform logs for the modified stack and Terramate’s skip messages for the rest.
Trade‑offs and limitations
- Rebasing or force‑pushes: Because detection depends on linear commit history, rewriting history can cause Terramate to miss changes. If you rebase a feature branch, run a full
terramate run terraform apply(without--changed-only) once to resynchronize the hidden state, then resume using the flag. - Shared module changes: If a module used by several stacks is updated but the stacks themselves have no file changes, the
--changed-onlyflag will skip those stacks even though they may be affected. Mitigate this by either bumping a version in the module’s source path (so each stack’s.tffile changes) or periodically running a full execution to drift‑check all stacks. - Provider version: The feature works with Terramate ≥0.12.0 and any recent Terraform version; older Terramate releases may lack the
.terramatestate handling.
Actionable closing
Add the following steps to your CI pipeline (e.g., GitHub Actions, GitLab CI):
# Update generated backend/variable files
- run: terramate generate
# Run Terraform only on stacks that changed since last commit
- run: terramate run terraform plan --changed-only
# If the plan succeeds, you may optionally apply
- run: terramate run terraform apply --changed-only -auto-approve
After each merge, consider scheduling a nightly full run (terramate run terraform plan without the flag) to catch any drift caused by rebases or shared‑module updates. This keeps the change‑detection optimization reliable while still delivering fast feedback for the majority of pull requests.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.