Filtered Terragrunt Runs (Run Only Changed Units)
Related Guides:
Creating New Firefly Workflows: How to create a workspace and choose its Terragrunt version.
Path Configurations (Change-Based Triggers): Deciding whether a workspace runs at all.
Triggering Workspace Deployment: Manually triggering a deployment from the UI.
A Terragrunt workspace with Run All enabled runs every unit under its working directory on every trigger. In a repository with dozens of units, a one-line change to a single database configuration still plans everything — slow, noisy, and expensive.
Filtered runs narrow each run to the units your commits actually touched, plus any unit that depends on them. A change to one unit plans one unit. Everything else is skipped.
This is especially useful for:
Large unit trees, where a full
run --alltakes many minutes but a typical change touches one or two units.Shared repositories, where several teams commit to the same Terragrunt root and each wants feedback only on their own units.
Pull request reviews, where a plan covering thirty untouched units buries the one plan a reviewer needs to read.
Prerequisites
A GitHub or GitLab repository
Firefly works out the commit range from the provider. Bitbucket and Azure DevOps cannot supply one.
A Terragrunt workspace
The feature filters Terragrunt units. It does not apply to plain Terraform or OpenTofu workspaces.
Run All enabled
Filtering narrows a run --all run. With Run All off, the workspace already runs a single unit and there is nothing to filter.
Terragrunt 1.1.1 or newer
Earlier versions cannot expand a filter across the dependency graph. Firefly will not filter a run below this version.
Filtered runs are being rolled out per account. If the Filter Changed Units section does not appear in your workspace settings, contact your Firefly account team to have it enabled.
Supported VCS Providers
Filtered runs are available on GitHub and GitLab.
GitHub
Supported
GitLab
Supported
Bitbucket
Not supported
Azure DevOps
Not supported
On Bitbucket and Azure DevOps, Firefly cannot work out the range of commits a run covers, so it has nothing to hand Terragrunt and cannot filter. Leave Run only changed units off on workspaces backed by those providers: a pull request run that asks for a filtered plan will fail rather than quietly planning everything.
Enabling Filtered Runs
You can enable filtering when you create a workspace, or on an existing one.
Open the workspace and go to its General Configuration settings.
Set the IaC type to Terragrunt and choose a Terragrunt version of 1.1.1 or newer.
Enable Run All.
Under Filter Changed Units, turn on Run only changed units.
Save the workspace.
The setting is also available in the Bulk Onboarding wizard, so you can enable it across many workspaces as you onboard them.
Turning Run All off clears Run only changed units — the two settings are saved together, and filtering has no meaning without Run All.
No change to your repository is required. You do not need to add configuration files, annotate your units, or declare which files belong to which unit.
We Use Terragrunt's Own Filtering
Firefly does not calculate the list of units to run, and does not parse your Terragrunt configuration to work out what changed.
Instead, Firefly works out the range of commits your run covers and hands that range to Terragrunt using Terragrunt's own built-in change filter:
Terragrunt reads its own dependency graph and decides which units fall inside that range. The leading ... is what tells Terragrunt to also include units that depend on a changed unit.
This matters for two reasons:
The unit selection follows Terragrunt's rules, not ours. If Terragrunt considers a unit affected, it runs. Behavior matches what you would get running the equivalent Terragrunt command yourself.
The behavior can change with your Terragrunt version. Because the selection is Terragrunt's, upgrading the Terragrunt version on your workspace may change which units are selected. The examples below were verified against Terragrunt 1.1.1.
How Change Discovery Works
Terragrunt compares the two ends of the commit range, works out which files changed between them, maps those files to the units that own them, and then walks the dependency graph to add every unit that depends on a selected one.
Example
Consider a workspace whose working directory contains three units, where api consumes an output from network:
With Run only changed units enabled:
database/terragrunt.hcl
database — 1 unit
Nothing depends on database, so the change stops there.
network/terragrunt.hcl
network and api — 2 units
api declares a dependency on network, so it is pulled in automatically.
README.md
none
No unit owns the file. The run completes with nothing to plan.
database/ and api/
database and api — 2 units
Both are touched directly. network is untouched and nothing depends on it changing.
Without filtering, every one of these pull requests would run all three units.
Which Commits Are Compared
The range Firefly sends depends on how the run was triggered:
Pull request opened or updated
The point where your branch diverged from the target branch, up to the latest commit on the branch
Apply of an approved pull request run
The same range that was planned
Merge of a pull request, or any other push to the workspace's default branch
The commit the branch pointed at before the push, up to the pushed commit
Manual deployment of a non-default branch
The point where the branch diverged from the default branch, up to the commit being deployed
Manual deployment of the default branch
Not filtered — every unit runs
A push and a manual deployment are different triggers even on the same branch. A push carries its own before and after commits, so it can be filtered; a manual deployment names one commit with nothing to compare it against. A push to any other branch does not start a run at all — a workspace only reacts to pushes on its own default branch.
Filtering applies to both the plan and the apply. When you approve a filtered plan, the apply covers the same units, so what you reviewed is what gets applied.
How Filtering Interacts with the Working Directory
Enabling filtering does not change what your working directory is for. Two separate decisions are made, in order, and filtering only affects the second:
Does this workspace run at all? Unchanged. A workspace runs when a changed file falls under its working directory, or matches one of its path configurations. This is how Firefly decides the workspace is affected, with or without filtering.
Which units inside it run? This is what filtering adds. Your working directory is the root Terragrunt runs from, and the filter narrows the units beneath it.
Filtering only ever narrows. It cannot widen a run beyond the working directory, and a change outside the working directory never selects a unit inside it.
A Run Can Be Triggered and Then Select Nothing
The two decisions are made against different things — the first against file paths, the second against Terragrunt's unit graph — so a change can satisfy the first and not the second.
The clearest example is a file that lives under your working directory but belongs to no unit, such as a README.md:
The file is under the working directory, so the workspace is marked as changed and a run starts.
No unit owns the file, so the filter selects no units and the run finishes without planning anything.
The same change on a workspace without filtering would have planned every unit.
This is easy to mistake for a workspace that did not run. A run that selects no units posts no plan comment on the pull request, so the pull request looks the same as if the workspace had been skipped entirely. The run itself exists — open the workspace in Firefly, where it is recorded as completed with no changes to plan.
Limitations
Branch creation is not filtered. The first push that creates a branch has no earlier commit to compare against, so that run covers every unit.
Manual deployments of the default branch are not filtered. There is no other branch to compare the default branch against, so these runs cover every unit.
Destroy runs are never filtered. A destroy tears down the whole workspace, so every unit runs regardless of this setting.
Only files that Terragrunt attributes to a unit are detected. Terragrunt maps changed files to units through its own configuration graph. A file that a unit reads at runtime but that Terragrunt does not treat as part of that unit — for example a data file loaded by your module — will not cause that unit to be selected. Changes to a module's .tf code are detected. If you depend on external files that Terragrunt cannot see, keep a full run for that workspace.
Runs fall back to a full run when the range cannot be determined. If Firefly cannot work out the comparison range — for example the branch history is unavailable — the run executes every unit rather than silently running too few.
Filtering narrows units within a workspace, not which workspaces run. Deciding whether a workspace is triggered at all is a separate mechanism — see Path Configurations.
Last updated
Was this helpful?