How to use OpenTofu Exclude

OpenTofu --exclude vs. --target

Infrastructure as Code (IaC) tools like OpenTofu have changed how we manage cloud resources. The usual workflow involves planning and applying changes to your entire configuration. However, in complex, large-scale environments, or during specific operational scenarios like troubleshooting or phased rollouts, applying everything every time isn't always practical. This is where selective operations come into play.

OpenTofu offers two primary command-line flags for this purpose: the long-standing --target and the more recent --exclude. Understanding their difference and appropriate use cases is key to efficient and safe infrastructure management. While these CLI tools offer granular control, it's also worth noting that managing the broader lifecycle, governance, and collaboration around IaC often benefits from overarching platforms that can enhance visibility and control, such as Scalr.

The --target Flag: Focusing In

The --target flag allows you to narrow the scope of tofu plan or tofu apply operations to specific resources and their upstream dependencies. Anything not targeted or depended upon by a target is ignored.

Syntax:

tofu plan -target=<RESOURCE_ADDRESS>
tofu apply -target=<RESOURCE_ADDRESS_1> -target=<RESOURCE_ADDRESS_2>
  • RESOURCE_ADDRESS can be a specific resource instance (e.g., aws_instance.example[0]), a whole resource (e.g., aws_instance.example), or an entire module (e.g., module.my_module).

Common Use Cases for --target:

  • Troubleshooting: Isolating a misbehaving resource to re-apply its configuration.
  • Iterative Development: Applying and testing changes to a new component in isolation.
  • Disaster Recovery: Quickly re-provisioning specific failed components.

Limitations of --target: While useful, --target has its downsides:

  • Cumbersome for Multiple Resources: Specifying many targets is tedious and error-prone. Community discussions have even floated ideas like --target-file to alleviate this.
  • Risk of Configuration Drift: Routinely targeting subsets can lead to other resources drifting from their defined state, as they aren't being evaluated. This undermines the "source of truth" principle of IaC.
  • "Tunnel Vision": It's easy to miss indirect dependencies or the impact on the system if not careful.

The --exclude Flag: Strategically Omitting

Introduced in OpenTofu 1.9.0, the --exclude flag is the logical counterpart to --target. It instructs OpenTofu to operate on all resources except those specified and any resources that depend on them (downstream dependencies).

Syntax:

tofu plan -exclude=<RESOURCE_ADDRESS>
tofu apply -exclude=<RESOURCE_ADDRESS_1> -exclude=<MODULE_ADDRESS>

For example:

# Exclude a specific S3 bucket and an entire networking module
tofu apply -exclude=aws_s3_bucket.sensitive_logs -exclude=module.legacy_network

Key Distinction: You cannot use --target and --exclude in the same command. You must choose one approach.

Dependency Handling with --exclude: This is critical: excluding a resource also excludes everything that depends on it. For instance, excluding a core networking module might also exclude compute instances or load balancers relying on its outputs. A solid understanding of your dependency graph is essential.

When --target Isn't Ideal (And --exclude Might Be Better)

The introduction of --exclude addressed scenarios where --target felt awkward or impractical:

  1. Applying to the Majority of a Large Configuration: If you need to update 95 out of 100 resources, listing 95 -target flags is inefficient and risky. It's far simpler to use -exclude for the 5 resources you want to skip.
  2. Intent is "Everything But These Few": When your mental model is "update everything except X, Y, and Z," --exclude directly translates that intent into your command, making it more readable and self-documenting.
  3. Reducing Command Line Clutter: A few -exclude flags are cleaner than a potentially long list of -target flags, improving readability for manual execution and CI/CD scripts.
  4. Decreasing Risk of Forgetting Inclusions: With --target for a broad update, you risk forgetting a resource that should have been included. --exclude defaults to including everything not explicitly omitted (or dependent on an omission).

After (Clearer with --exclude):

tofu apply -exclude=resource.x -exclude=resource.y -exclude=resource.z

Before (Impractical with --target):

# Imagine listing dozens or hundreds of targets...
tofu apply -target=resource.a -target=resource.b ... (and 93 more)

Key Scenarios and Advantages for --exclude

  • Managing Large Configurations with Few Exceptions: As noted, this is win for --exclude. If a module is under maintenance or a resource is unstable, excluding it is easy.
  • Phased Rollouts and Testing: Incrementally introduce changes by excluding certain regions or resource types initially. For example, deploy a new feature to a staging environment while excluding production resources.
  • Temporarily Bypassing Problematic Resources: If a resource has drifted or is causing apply errors, --exclude allows you to proceed with other updates while you investigate the problematic component.
  • Simplifying Operations by Inverting Logic: When omission is the goal, --exclude aligns with that operational logic, reducing cognitive load.

Summary Table: --target vs. --exclude

Feature

--target

--exclude

Primary Function

Include only specified resources & their dependencies.

Exclude specified resources & their dependents.

Operational Logic

Inclusion

Exclusion

Dependency Handling

Includes upstream dependencies of targeted resources.

Excludes downstream resources that depend on excluded items.

Pros

Precision for isolated changes; clear scope for single-item focus.

Simplicity for broad changes with few exceptions; clearer "omit" intent.

Cons

Cumbersome for many targets; risk of forgetting inclusions.

Risk of over-exclusion due to cascading dependencies; needs graph knowledge.

Mutual Exclusivity

Cannot be used with --exclude.

Cannot be used with --target.

Drift Risk

Yes, if used routinely without full applies.

Yes, if used routinely without full applies.

Best Practices and Broader Considerations

While powerful, both --target and --exclude deviate from the standard "apply everything" workflow and should be used judiciousely.

  • Prefer Full Applies: Whenever possible, full applies are best to ensure your entire infrastructure aligns with your code, decreasing drift.
  • Always plan Before apply: Carefully review the execution plan to confirm the scope of changes is exactly what you intend.
  • Version Control and CI/CD: For anything beyond a quick fix, the intent and commands should be version-controlled. CI/CD pipelines using these flags need clear documentation and careful control. This is an area where platforms like Scalr add value by providing robust frameworks for versioning, approval workflows, and policy enforcement around IaC operations.
  • Configuration Drift: This is a risk with any partial apply strategy. Regularly scheduled full applies are crucial. Tools that offer automated drift detection, a feature often found in comprehensive IaC management platforms like Scalr, can proactively alert you to discrepancies.
  • Team Communication: Ensure clear communication when performing partial applies, especially in shared environments.

Conclusion: Choosing the Right Tool for the Job

OpenTofu's --target and --exclude flags provide essential flexibility for managing complex infrastructure.

  • Use --target for small, well-defined, inclusive operations.
  • Use --exclude when omitting a few items from a broader operation is simpler and clearer.

These flags are valuable tools in an operator's toolkit. However, managing IaC effectively at scale involves more than just CLI commands. It requires a holistic approach to governance, collaboration, cost management, and security. Platforms like Scalr complement tools like OpenTofu by providing the necessary guardrails, visibility, and automation to manage the entire lifecycle of your infrastructure, ensuring that even granular operations fit within a well-defined and secure operational model. By understanding both the low-level controls and the high-level management strategies, teams can truly master their Infrastructure as Code.