skip to content

What does the `-target` option do to a `terraform plan` or `terraform apply`, and why does Terraform treat it as a tool for exceptional circumstances rather than routine use?

level: middleimportance: must knowfreq 65%

answer

  1. narrows the run, on purpose
  2. dependencies in, dependents out
  3. refresh is narrowed as well
  4. Terraform warns the apply is incomplete
  5. always finish with an untargeted plan

basics

~20 s

Terraform's -target restricts a run to the addresses you name plus what they depend on, skipping the rest of the configuration and most of its refresh. The apply is therefore deliberately incomplete, which is why a full untargeted plan must follow it.

solid answer

~50 s

`-target=ADDRESS` narrows the graph Terraform walks to the objects you name and everything they depend on. Anything else in the configuration is ignored for that run — not planned, and not refreshed. That is useful in genuine emergencies: recovering after an apply failed halfway, working around a provider bug, or breaking a dependency problem during a refactor, and Terraform itself sometimes suggests it in an error message. It is an escape hatch because the result is a partial apply: resources that *depend* on your target are not included, output values may be left stale, and drift elsewhere goes unnoticed. Terraform prints a warning saying exactly that and telling you to run `terraform plan` with no targets afterwards. The rule I follow is that a targeted apply is not finished until the following untargeted plan comes back clean.

code

bash · 2 lines
bash
terraform apply -target=module.db -target=aws_security_group.db
terraform plan

go deeper

for a junior

Know that this option limits a run to the resources you name and that the rest of the configuration is skipped, so it is not the normal way to apply changes.

for a middle

Explain the graph reduction precisely: the targets plus what they depend on are included, dependents are not, refresh is narrowed, and Terraform warns that the apply may be incomplete.

for a senior

Demonstrate the incident discipline — targeted apply to get out of trouble, then an untargeted plan before you consider the change finished, plus a read of what the partial run left stale for neighbouring stacks.

for a principal

Own the policy: pipelines never target, break-glass targeting is a human action that is logged and followed up, and habitual targeting is treated as a signal to split the root module rather than as a workflow.

## What the option accepts `-target` takes a resource address and can be repeated: `terraform apply -target=aws_instance.web -target=aws_security_group.web`. It also accepts module addresses — `-target=module.network` selects everything inside that module, including nested modules — and instance addresses with a key, such as `-target='aws_instance.web[0]'`. It is available on `plan`, `apply` and `destroy`. ## The graph semantics — dependencies in, dependents out This is the mechanism candidates half-know. Terraform builds its dependency graph as usual and then reduces it to the targeted nodes **plus everything those nodes depend on**, because a target cannot be created without the things it needs. What it does *not* pull in is the other direction: resources that depend on your target are excluded. If you target a subnet, the instances placed in it are not in the run; if you target a database, the application that reads its endpoint is not in the run. That asymmetry is the entire source of surprise. The thing you changed is updated; everything that consumes what you changed is not. ## Refresh is narrowed too A targeted run does not refresh the whole state. Terraform reads real-world attributes only for the objects it is actually working with, so drift on the rest of the estate is neither discovered nor recorded during that run. A targeted apply therefore leaves state that is fresh in one corner and as stale as it was before everywhere else. ## Output values Root module outputs that depend on untargeted resources may not be updated, which matters more than it sounds: another configuration may be reading those outputs through remote state, so a stale output silently feeds a wrong value to a neighbouring stack. ## The warning, and what it tells you to do After a targeted run Terraform prints a warning that the applied changes may be incomplete, that some configured changes may have been ignored and outputs may not be fully updated, and that you should run `terraform plan` to verify nothing else is pending. It goes further and says outright that the option is not suitable for routine use and exists for exceptional situations such as recovering from errors. The docs mean it. Quoting that discipline back — *targeted apply, then immediate untargeted plan* — is what most interviewers are listening for. ```bash terraform apply -target=module.db # emergency, narrow terraform plan # mandatory follow-up: expect empty ``` ## Legitimate uses - **Recovering from a failed apply.** Half the changes went in, one resource errored, and re-running the whole thing would take an hour you do not have during an incident. - **Working around a provider bug** that makes an unrelated resource fail to plan, so nothing at all can be applied until it is skipped. - **Refactoring**, where a chicken-and-egg ordering means one piece has to exist before the rest of the configuration can even be evaluated. - **When Terraform tells you to.** Some error messages explicitly suggest a targeted run as the recovery step. ## Why routine use is a smell Teams reach for `-target` habitually for two reasons, and both are structural rather than technical. Either the root module has grown so large that a full plan takes too long, or the blast radius is so frightening that nobody wants to see the whole diff. Neither is fixed by a flag. The fix is smaller root modules with narrower state, so a normal, complete apply is fast and boring enough to run every time. Using `-target` to avoid an unwanted change in the same configuration is worse still: the change is still in the code, it is still going to happen, and you have only chosen who gets surprised by it. In a pipeline, the sensible policy is that automated applies never pass `-target`, and that a targeted run is a break-glass action performed by a human, recorded in the incident notes, with a follow-up task to get the untargeted plan back to empty. ## Don't confuse it with -replace `-target` changes *which objects the run considers*. `-replace` changes *what action is planned for an object*. They can be used together, but they solve different problems, and swapping them in an answer is an immediate tell.

  • Can -target point at a module, and can it be given more than once?
    Yes to both. `-target=module.network` selects every resource inside that module and any modules nested in it, and you can repeat the option to build up a set of addresses in one run. The partial-apply semantics are unchanged: dependencies of those objects come along, dependents do not, and the follow-up untargeted plan is still required.
  • Why does a failed apply sometimes justify a targeted run?
    Because a partial apply has already changed real infrastructure, and re-running everything can be slow or can re-attempt work you do not want repeated during an incident. Targeting the resource that failed gets the estate to a consistent point quickly. It is a recovery step, so it ends with the full plan, not with going home.
  • A team's production runbook says to always apply with -target. What does that tell you?
    That the root module is too big and its full plan is too slow or too frightening to run, so people are managing risk with a flag instead of with structure. The real fix is smaller root modules with narrower state so a complete apply is routine. Meanwhile the estate is quietly accumulating changes nobody has ever planned.

saying these in an interview costs you the question

  • Thinks -target also includes resources that depend on the target
  • Uses -target routinely to make applies run faster
  • Believes a targeted apply still refreshes the whole state
  • Treats the follow-up untargeted plan as optional
  • Confuses -target with -replace: narrowing versus recreating

context