Running Terraform Only on Changed Stacks with Terramate
Learn how to run Terraform commands only on the stacks whose files have changed since the last Git commit using Terramate’s --changed flag.
28 Aug 2026, 07:28 UTC

Desired outcome
Execute Terraform commands (e.g., init, plan, apply) only on those stacks whose source files have changed since the last Git commit, leaving unchanged stacks untouched to save time and avoid unnecessary state operations.
Prerequisites
- Terramate CLI installed, version ≥ 0.10 (the
--changedflag was introduced in v0.10.0). - Terraform CLI available in the same environment.
- A Git‑initialized repository that contains a
.terramatedirectory with stack definitions and aterramate.config.hclfile. - Working directory clean (no uncommitted or untracked changes) unless you intend to use
--allow-dirty.
Procedure
- Commit the current state so Terramate has a baseline to compare against:
git add . git commit -m "Baseline before changes" - Modify one or more stack files** (e.g., edit
network/main.tfor add a new variable file). - Run the desired Terraform command through Terramate with the
--changedflag**. Example: initialize and plan only changed stacks:
Terramate internally runsterramate run --changed terraform init terramate run --changed terraform plangit diff --name-only HEADto list changed files, maps those files to stacks defined in.terramate, and executes the command in parallel for each affected stack. - Observe the output** – you should see log lines prefixed with the stack name for each stack that was processed, and no output for stacks that were unchanged.
Expected checks
- The command output lists only the stacks that Terramate identified as changed (e.g.,
[network] Running terraform init). - Each listed stack shows the normal Terraform output for the invoked command.
- The process exits with code 0 if all invoked commands succeed; unchanged stacks are silently skipped.
- If you run the same command without
--changed, you should see output for every stack in the repository, confirming that the flag correctly limits execution.
Recovery options
- If a stack fails (e.g., a syntax error in
network/main.tf), fix the error in the source file, then re‑run the exact sameterramate run --changed …command. Terramate will again detect the changed file and retry only that stack. - To process all stacks (e.g., after a failed run you want to verify everything), omit the flag:
terramate run terraform plan. - To retry only the stacks that failed in the previous run, you can use
terramate run --retry terraform apply(requires Terramate ≥ 0.13).
Limitations and practical verification
- Change detection depends on an unmodified Git working directory. Uncommitted or untracked changes are ignored, which may cause Terraform to run on stale code. Verify cleanliness with
git status --porcelain; if you have pending work, either commit it first or add--allow-dirtyto the Terramate command. - Parallel execution assumes your Terraform backend supports concurrent state operations. If you use a backend that locks state per operation (e.g., default local backend with multiple simultaneous
applycalls), you may encounter state‑locking errors. Test concurrency in a non‑production environment or serialize runs by adding--max-parallel 1. - The
--changedflag compares the working tree to the most recent commit. If you have not committed recent changes, Terramate will not see them. Always commit before running, or use--allow-dirtyto include uncommitted modifications. - Practical way to check the result: after running
terramate run --changed terraform plan, rungit diff --name-only HEADmanually and compare the list of files to the stack names shown in the Terramate output. They should match.
Example configuration
Suppose your repository contains the following structure:
.
├── .terramate
│ ├── network
│ │ └── terramate.hcl
│ └── app
│ └── terramate.hcl
├── terramate.config.hcl
├── network
│ └── main.tf
└── app
└── main.tf
terramate.config.hcl may be minimal:
# terramate.config.hcl
cli {
version = ">=0.10.0"
}
Each stack’s terramate.hcl simply tells Terramate to manage Terraform:
# .terramate/network/terramate.hcl
terraform {}
After committing the baseline, edit only network/main.tf. Running:
terramate run --changed terraform plan
produces output similar to:
[network] Running terraform plan
... (Terraform plan output for network)
No lines appear for the app stack, confirming that unchanged stacks were skipped.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.