Terraform

Terraform -target Partial Apply: When to Use It and What to Watch For (Associate Prep)

2026-04-19
NicheeLab Editorial Team

Terraform's -target option lets you plan and apply just a specific resource or module. It looks convenient, but the official documentation explicitly discourages everyday use — mishandling the dependency relationships is a common source of state inconsistency.

This article walks through -target from the perspective of the dependency graph and state, lays out a safe procedure for the limited situations where you really need it, and summarizes the alternatives Terraform recommends instead. We also cover the points the Associate exam tends to ask about.

What -target Does and HashiCorp's Official Stance

-target narrows the plan/apply scope to just the addressed object (a resource or a module) and its surroundings. Upstream prerequisites the target needs are pulled in automatically, but downstream dependents that rely on the target are not.

HashiCorp's documentation recommends -target only as an exceptional measure for recovery or workarounds. Leaning on it in day-to-day operations leaves updates outside the dependency chain stranded, and the next full apply tends to surface unexpected drift.

You can pass -target to both plan and apply, but the safe pattern is to plan first, review the diff, and then apply. If you save a plan file, that plan is itself scoped to the targeted objects only.

  • When to use it: isolating a failing resource, working around external constraints (quotas, deployment windows), or pre-creating long-running resources
  • When to avoid it: as a substitute for routine staged deployments, when dependencies are complex, or right after a sweeping schema change
  • Address examples: aws_instance.web[0], module.app, module.db.aws_security_group.sg

Basic command examples

terraform plan -target=module.app -target=aws_instance.web[0]
terraform apply -target=module.app
# Save the plan, then apply it
terraform plan -target=aws_security_group.web -out=plan.tfplan
terraform apply plan.tfplan

Understand Partial Apply Through the Dependency Graph

Terraform decides execution order from the dependency graph. -target extracts just the targeted object and its upstream dependencies from that graph and processes them. Dependents (the side that depends on the target) are excluded, so downstream updates do not cascade.

As a result, if the target's update changes the inputs of a dependent, that dependent stays stale. This is exactly what drives large diffs or surprising replacements (create-before-destroy and friends) on the next full apply.

  • Upstream dependencies are pulled in automatically (e.g. if you target an app SG that references a DB password, the resource that emits that password may be included)
  • Dependents are not included (e.g. targeting a VPC does not pull in the subnets and routes hanging off it)
  • Data sources are evaluated when referenced, but outputs of resources outside the plan scope do not get refreshed — keep that in mind

How the dependency graph is sliced when you target

A (vpc)
 \
  B (subnet) -> D (instance)
 /
C (sg)

With -target=B:
  Included: B and A (the upstream B depends on, if needed)
  Excluded: D (depends on B), C (unless B references it)

Example of these dependencies in HCL

resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16"
}

resource "aws_subnet" "app" {
  vpc_id     = aws_vpc.main.id
  cidr_block = "10.0.1.0/24"
}

resource "aws_instance" "web" {
  subnet_id = aws_subnet.app.id
  # ...
}

# -target=aws_subnet.app includes the VPC, but aws_instance.web is not processed

State and Diff-Management Pitfalls

Repeated partial applies tend to leave non-targeted resources drifting from what's actually in the cloud, even when state itself is up to date. The classic symptom is that the next full plan emits a huge diff and becomes hard to review.

With count/for_each over lists or maps, updating only part of the set can cause index reshuffling or new-key insertions to trigger unexpected replacements on the next full apply. Watch out for interactions with lifecycle settings like create_before_destroy and ignore_changes as well.

Outputs and module outputs can keep returning stale values when they sit outside the target scope. Even when the dependency is indirect, operate on the assumption that you will reconcile everything with a full apply afterwards.

  • Always run a full plan after a partial apply to inspect drift
  • The most common sources of destructive surprises: networking layers, IAM policy dependencies, and storage lifecycle rules
  • Don't pile up partial applies over time — keep it to a short-term workaround

What the diffs look like in each case

# Partial apply
terraform plan -target=module.db
terraform apply -target=module.db

# Immediately verify consistency with a full plan
terraform plan  # Check whether the app or network layer surfaces unexpected diffs

# Be especially careful when count/for_each changes are involved
# Example: after adding an element to the for_each source, a partial apply that creates only some entries can trigger reshuffling on the next full apply

Real-World Use Cases and a Safe Operating Procedure

The official intent is a temporary measure for triage or for working around external constraints. For instance: a specific resource is hitting a provider API limit and blocking everything else, so you either skip it and move the rest forward, or do the inverse and create just the minimum prerequisite up front.

To use it safely, stick to the cycle: clearly identify the target, review the diff thoroughly, run a full plan check after the apply, and close the loop by converging with a full apply within a short window.

  • Procedure template: 1) Diagram the blast radius and confirm the target plus its upstream dependencies 2) Run terraform plan -target=... (possibly several times) to scrutinize the diff 3) Apply in stages if necessary, slicing it small 4) Immediately run a full terraform plan to surface any inconsistencies 5) Once stakeholders sign off, converge with a full apply within a short window
  • Operational tip: use specific resource addresses for the target — avoid sweeping, wildcard-like scopes
  • Even when using it to pre-create long-running resources (RDS, GKE, etc.), don't leave the downstream dependency updates on the floor

Specifying multiple targets and staged application

# Slice targets in dependency order (example)
terraform plan  -target=aws_vpc.main -target=aws_subnet.app
terraform apply -target=aws_vpc.main -target=aws_subnet.app

# Application layer after the prerequisites are created
terraform plan  -target=module.app
terraform apply -target=module.app

# Always finish with a full plan
terraform plan

Alternatives and Best Practices

In most cases there's a safer option than -target. For replacing a specific object, use -replace; for refreshing state without changes, use -refresh-only; to shrink blast radius structurally, split the configuration into separate stacks (workspaces or repos).

When restructuring, declare renames explicitly with moved blocks and allow temporary drift with ignore_changes — small touches that stabilize the plan. Establishing a rule that every partial apply must converge with a full apply within a short window also cuts down on incidents.

  • Re-create a specific resource: terraform apply -replace=aws_instance.web[0]
  • Refresh state only: terraform plan -refresh-only, then terraform apply -refresh-only if it looks clean
  • Reduce blast radius: split state, use workspaces, and revisit module boundaries
MechanismPrimary purposeScope and characteristicsMain risks and caveats
-targetPartial plan/applyLimited to the target and its upstream dependencies. Dependents are excludedNot recommended for everyday use. Unmodified parts surface as a large diff on the next full apply
-replace=ADDRRe-create a specific objectReplaces only the target. Dependencies are evaluated via the normal graphWatch for side effects like downtime or IP address changes
-refresh-onlyReflect real infrastructure state into Terraform stateNo create/update/delete — read-onlyUseful for surfacing drift, but you still need a separate apply to reconcile diffs

Concrete examples of the alternatives

# Prefer -replace when the goal is replacement
terraform plan  -replace=aws_instance.web[0]
terraform apply -replace=aws_instance.web[0]

# When you just want to refresh state and see the impact
terraform plan  -refresh-only
terraform apply -refresh-only

# Declare renames and moves explicitly via moved blocks
moved {
  from = aws_security_group.old
  to   = aws_security_group.new
}

Key Points for the Associate Exam

Exam questions tend to probe the nature of -target (exceptional use only, upstream included, downstream excluded) and your awareness of its risks. Whether it is recommended for everyday operations and which alternative you would pick are common decision points.

Connecting the topic to operational practice — address granularity (resource, module, instance index), what ends up in the plan file, the importance of a full plan after the apply — makes the answer choices easier to navigate.

  • Use -target only as an exception — it is not the first choice for steady-state operations
  • Dependency graph: upstream included, downstream excluded
  • Alternatives: -replace for replacement, -refresh-only for state sync, configuration splitting to shrink blast radius
  • Always run a full plan after a partial apply to verify consistency
  • Be precise with addresses (module.foo, aws_xxx.res[0], and so on)

Sorting out the commands that are easy to mix up on the exam

# Partial apply (exceptional)
terraform plan  -target=module.app
terraform apply -target=module.app

# Replacement (the recommended way to explicitly re-create)
terraform apply -replace=aws_db_instance.main

# State sync only
terraform plan  -refresh-only

Check Your Understanding

Associate

問題 1

A team wants to create just a particular subnet and the instances that depend on it first. When using Terraform's -target option, which of the following best describes the behavior?

  1. The targeted subnet and the instances that depend on it are excluded, while the subnet's upstream dependencies (such as the VPC) are included in the plan
  2. The targeted subnet, its upstream dependencies, and its downstream dependents are all included automatically
  3. Only the targeted subnet is included in the plan; neither its upstream dependencies nor its downstream dependents are
  4. Only the targeted subnet and its downstream dependents are included; upstream dependencies are not

正解: A

-target includes the targeted object and its upstream dependencies, but never its downstream dependents. Targeting the subnet therefore pulls in upstream resources like the VPC, while the instances that depend on the subnet are left out.

Frequently Asked Questions

If I point -target at a module, does it include everything under that module?

Yes — the resources under that module are included by default. Any dependencies outside the module that the target needs are also pulled in. However, other modules that depend on the target module (downstream dependents) are not included.

Do I need to run terraform refresh after a partial apply?

Modern Terraform no longer has a dedicated refresh command — you sync state via plan/apply with the -refresh-only flag. The safe pattern after a partial apply is: run a full terraform plan to inspect drift, use terraform plan -refresh-only to update state only if needed, and finally run a full apply to converge.

Does depends_on change how -target behaves?

No, it does not. -target includes the target object and its upstream dependencies (whether implicit or explicit via depends_on), but never its downstream dependents. depends_on shapes the dependency graph itself, but the rule that -target excludes dependents still holds.

Check what you learned with practice questions

Practice with certification-focused question sets

無料で問題を解いてみる
Author

NicheeLab Editorial Team

NicheeLab editorial team focused on data engineering and cloud certification learning. Content is structured around practical study needs and official exam domains.


Related articles
Terraform

HCL Syntax: Terraform's Configuration Language (2026)

HCL2 fundamentals for Terraform — blocks, attributes, expres...

Terraform

Terraform Authoring & Operations Pro: Complete Guide (2026)

Tactics for the Terraform Pro exam — module authoring, works...

Terraform

Terraform Providers: Plugin Management Fundamentals (2026)

Provider mechanics — required_providers, versions, mirrors, ...

Terraform

Terraform Resource Blocks: Declarative Infra Units (2026)

Resource block fundamentals — addresses, references, common ...

Terraform

Terraform Data Sources: Read-Only External Data (2026)

Data source basics — declaration, refresh behavior, dependen...

Browse all Terraform articles (102)
© 2026 NicheeLab All rights reserved.