Terramate Stack-Based Change Detection: Architecture Note
How Terramate’s stack‑based change detection works, what it requires, where trust boundaries lie, and how to verify selective execution in practice.
24 Aug 2026, 06:49 UTC

Requirements
To use Terramate’s selective execution feature you need:
- A Git repository that contains the Terramate project.
- Each infrastructure component represented as a
stackwith its ownterramate.hclfile. - Terramate version 0.10.0 or newer (the
changedfilter was introduced in this release). - Access to the local file system and Git metadata; no network calls are made unless you enable remote caching or drift checks explicitly.
If any of these conditions are not met, Terramate falls back to a full‑run execution or may miss changes.
Smallest Suitable Design
The minimal design that enables change detection consists of three parts:
- Stack definition – each stack declares its Terraform files and optionally a
depends_onblock to express ordering. - Change detection layer – Terramate scans the Git history between the current HEAD and the last successful run (stored in a hidden
.terramatedirectory) to produce a list of stacks whoseterramate.hclor.tffiles have changed. - Selective executor – the
terramate runcommand receives the filtered list and invokes Terraform only for those stacks, respectingdepends_onfor ordering while parallelizing independent stacks.
This design keeps the blast radius limited to the stacks that actually changed and reduces runtime proportionally to the number of affected stacks.
Trust/Data Boundaries
Terramate operates entirely on the local workstation:
- File system – reads
terramate.hcl, Terraform files, and any local variable files. - Git metadata – reads commit objects and tree objects to compute diffs; it does not push or pull from remotes unless you configure a remote backend for Terraform state.
- External services – no code is sent to Terramate’s servers or third‑party APIs. If you enable the optional remote cache (
terramate cloud) or drift checks, then hashed file contents are transmitted, but the original HCL remains local.
Thus the trust boundary is the developer’s machine; any compromise of the local Git repository could affect detection, but Terramate itself does not introduce additional network exposure.
Operational Checks
Terramate provides several built‑in checks that run before or during execution:
- Formatting validation –
terramate fmt --checkverifies that all HCL files are correctly formatted. - Linting – integrates with
tflintand custom HCL linters to catch syntax issues early. - Drift detection – when enabled, Terramate runs
terraform planin a read‑only mode and compares the output against the stored state to flag manual changes. - Dependency validation – the
depends_onblock is verified for circular dependencies before the run starts.
These checks can be invoked manually or configured to run automatically in CI pipelines.
Failure Modes
Because execution is scoped to changed stacks, failures are isolated:
- If a stack’s
terraform applyreturns a non‑zero exit code, Terramate halts the run, marks the stack as failed, and skips any downstream stacks that declared adepends_onrelationship. - The error message includes the stack name and the underlying Terraform output, making troubleshooting straightforward.
- Upstream stacks (those that do not depend on the failed stack) remain unaffected and are not rolled back automatically; you must decide whether to re‑run them after fixing the failure.
Terramate does not attempt to roll back Terraform state; state rollback must be handled by your Terraform workflow or external tooling.
Conditions That Would Change the Design
Certain circumstances would require revisiting the minimal design:
- Non‑Git workflows – if stacks are managed outside Git (e.g., tarballs or external APIs), the change detection layer would need a different mechanism, such as file‑system watchers or explicit manifest inputs.
- Uncommitted changes – Terramate only considers committed history; local uncommitted edits are ignored unless you stage them. To detect uncommitted work, you would need to add a pre‑run
git diff --quietcheck or commit a temporary snapshot. - Large monorepos with frequent unrelated changes – if the Git history scan becomes a performance bottleneck, you might introduce a caching layer that records the last‑seen commit per stack, trading a bit of freshness for speed.
- Regulatory constraints on metadata export – if transmitting hashed file contents to a remote cache is prohibited, you would disable the remote cache feature and rely solely on local execution.
In each case, the core concept of scoping Terraform runs to affected stacks remains valid, but the implementation of the change detection layer would need adjustment.
Practical Verification
To confirm that selective execution is working as expected:
- Clone a Terramate‑enabled repository:
git clone https://example.com/org/infra.gitcd infra- Make a change to a single stack, e.g., edit
stacks/network/terramate.hcl. - Run the detection command:
terramate list --changed- You should see only the network stack listed.
- Execute a plan for the changed stacks:
terramate run terraform plan- Observe that Terraform runs only for the network stack; other stacks are skipped and reported as “unchanged”.
If you instead edit a file in an unrelated stack, the list will reflect that stack, and the plan will be limited to it. This behavior validates the change detection layer and the selective executor.
Example Configuration with Dependencies
The following snippet shows two stacks where web depends on network:
# stacks/network/terramate.hcl
terramate {
stack {
name = "network"
}
}
# stacks/web/terramate.hcl
terramate {
stack {
name = "web"
}
depends_on = ["network"]
}
When you run terramate run terraform apply after modifying only the network stack, Terramate will:
- Detect the network stack as changed.
- Run
terraform applyfor network. - Wait for network to finish.
- Then run
terraform applyfor web, because the dependency is satisfied. - If network fails, web is skipped and the error includes the stack name.
This demonstrates how Terramate respects ordering while still parallelizing independent stacks (e.g., a third monitoring stack with no dependencies would run concurrently with network).
Limitations
- Relies on a clean Git history; rebasing or force‑pushing after a Terramate run can cause the internal
.terramatecheckpoint to become stale, leading to false‑positive or false‑negative change detection. - Only files tracked by Git are considered; ignored files (per
.gitignore) will not trigger a run even if they affect Terraform behavior. - The selective execution feature is unavailable in versions prior to 0.10.0; older releases always execute all stacks.
To mitigate the first limitation, you can reset the checkpoint after a rebasing operation:
terramate purge-cache # removes .terramate directory, forcing a full detection on next run
Running this command is safe because it only deletes Terramate’s internal metadata; it does not affect your Terraform state or source code.
Summary
Terramate’s stack‑based change detection provides a lightweight, Git‑driven mechanism to limit Terraform execution to the stacks that actually changed. The smallest workable design requires a Git‑backed repository, per‑stack terramate.hcl files, and version 0.10.0 or newer. Trust boundaries stay local, operational checks catch formatting, linting, and drift issues, and failures are confined to the affected stack with clear error messages. Understanding the conditions that would alter the design—such as non‑Git workflows or uncommitted changes—helps you decide when the built‑in feature is sufficient and when you need to augment it with custom checks or external tooling.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.