linuxlab.io
Tutorials▾
  • Linux & networking
    File system, processes, TCP/IP, BGP and OSPF
    →
  • Terraform & IaC
    HCL, state, plan/apply on a LocalStack sandbox
    →
  • Git & GitHub
    Object model, plumbing, branching, GitHub Actions
    →
All tutorials →
PricingAboutSign inCreate account
/
Intro
Lessons
Footer
linuxlab-TutorialsPricingAboutPrivacy & cookies
Copyright © 2026 LinuxLab. All rights reserved.
linuxlab.io
Tutorials▾
  • Linux & networking
    File system, processes, TCP/IP, BGP and OSPF
    →
  • Terraform & IaC
    HCL, state, plan/apply on a LocalStack sandbox
    →
  • Git & GitHub
    Object model, plumbing, branching, GitHub Actions
    →
All tutorials →
PricingAboutSign inCreate account
/
  • Introduction
  • Lessons
  • How it works
  • Knowledge base
  • Cheat sheet
  • Capstone
  • Interview prep
home/terraform/kb/Workflow/tf-replace-target

kb/workflow ── Workflow ── beginner

-replace and -target: targeted operations on a single resource

The `-replace=<address>` and `-target=<address>` flags restrict apply to a single resource. `-replace` recreates the resource and replaces the deprecated `terraform taint`. `-target` applies only to the specified resource; it is an emergency tool, not an everyday one.

view as markdownaka: terraform-replace, terraform-target, taint

Why targeted operations exist

By default Terraform works with the entire project at once: one plan shows all changes, one apply applies them. Sometimes you need something specific:

  • Recreate one broken resource without touching the rest.
  • Apply only part of the configuration to avoid pulling in unrelated changes.
  • Work around a temporary bug in the provider on one resource.

For these cases there are -replace and -target.

-replace=<address>: recreate a resource

Forces Terraform to add a "destroy + create" action to the plan even when the code has not changed. Useful when a cloud resource is broken (a damaged EC2 instance, a stuck cache) but the HCL is correct.

bash
terraform apply -replace=aws_instance.web

The plan output:

  # aws_instance.web will be replaced, as requested
  -/+ resource "aws_instance" "web" {
      ...
  }
Plan: 1 to add, 0 to change, 1 to destroy.

This replaces the deprecated terraform taint. Before TF 0.15.2 you had to run terraform taint aws_instance.web; terraform apply, two steps and a manual state modification. Now it is one flag.

Addressing for -replace

Full resource addressing is supported:

bash
# plain resource
terraform apply -replace=aws_s3_bucket.demo
# count element
terraform apply -replace='aws_instance.web[0]'
# for_each element
terraform apply -replace='aws_s3_bucket.regional["eu"]'
# resource inside a module
terraform apply -replace='module.networking.aws_vpc.main'

Note the shell quotes around addresses that contain [, ], or ". Without quotes you get a shell error.

Multiple -replace flags

You can specify the flag more than once; all listed resources are recreated:

bash
terraform apply \
  -replace=aws_instance.web \
  -replace=aws_db_instance.main

-target=<address>: apply only the specified resource

Ignores everything except the named resource (and its dependencies):

bash
terraform apply -target=aws_s3_bucket.logs

Plan output:

Warning: Resource targeting is in effect
You are creating a plan with the -target option, which means that
the result of this plan may not represent all of the changes
requested by the current configuration.
  # aws_s3_bucket.logs will be created
  + resource "aws_s3_bucket" "logs" {
      ...
  }

Terraform warns you itself that this is a bad idea. It is not an everyday tool; it is an emergency one.

When -target is justified

  • You urgently need to create or change one resource while others are breaking the plan.
  • You are testing one module in a large project.
  • You are bootstrapping a new environment in stages (VPC first, then everything else).
  • You are resolving a circular dependency by temporarily removing one side.

When -target is a bad idea

  • Regular work. If you use it every day, something is wrong with the project structure. Split the configuration into separate state files instead.
  • In CI/CD. No automation should depend on -target.
  • To "work around" drift rather than fixing it.
  • In production without an explicit incident flag. Any -target in prod is a deviation from normal; it belongs in a runbook.

Why -target is problematic (HashiCorp's view)

From the Terraform docs:

Targeting is a powerful but disruptive feature, and so should be used only in exceptional circumstances.

Specifically:

  1. It creates a partially consistent state. After -target, the state and the cloud reality differ from what HCL describes. That gap can persist for hours if you forget to run a full apply later.

  2. It hides real dependencies. If resource A implicitly depends on B through a variable or data source, -target=A either fails or pulls in B unexpectedly.

  3. It complicates debugging. "Why is the ALB not working?" Because six weeks ago someone ran -target=alb and never applied the security_group updates.

That is why HashiCorp intentionally keeps the warning. It reminds you every time that you are doing something non-standard.

-target and dependencies

When a resource references others, those resources are also affected:

hcl
resource "aws_vpc" "main" { ... }
resource "aws_subnet" "private" {
  vpc_id = aws_vpc.main.id
}
bash
terraform apply -target=aws_subnet.private

This applies both the subnet and the VPC (because the subnet depends on the VPC). That makes -target slightly less dangerous: you cannot reference something that does not exist yet.

What these flags are not

  • -replace is not a manual destroy + create. It is an atomic operation in a single apply, with all dependencies handled.
  • -target is not a workspace. A workspace is a separate state using the same HCL. A target is a slice of one state.
  • -target is not a module boundary. Targeting module.networking covers the whole module, not just "networking isolation".

Common pitfalls

  • -target does not accept comma-separated values: use -target=A -target=B, not -target=A,B. Repeat the flag for each resource.

  • -replace does not work on data blocks. Data sources are read-only; there is nothing to recreate. To "re-read" a data source, the next plan/apply will refresh it automatically.

  • After -target, always run a full apply. Otherwise you will forget and the divergence between state and HCL stays permanently. A good habit is apply -target=X && apply in one script.

  • -replace marks the action only in the plan. The state itself does not change until apply. If the plan looks wrong, simply do not apply; nothing is broken.

  • -target does not work with import blocks. The declarative import introduced in TF 1.5+ applies to the entire configuration.

§ команды

bash
terraform apply -replace=aws_instance.web

Recreate a specific resource. Replaces the deprecated terraform taint.

bash
terraform apply -replace='aws_s3_bucket.regional["eu"]'

Recreate a specific for_each element. Quotes are required for the shell.

bash
terraform plan -replace=aws_instance.web

Run plan with -replace first to see what will happen before applying.

bash
terraform apply -target=aws_subnet.private

Apply only the specified resource and its dependencies. EMERGENCY tool.

bash
terraform plan -target=module.networking

Plan only for the module. Useful for bootstrapping new environments in stages.

§ см. также

  • tf-applyterraform apply: apply a plan to a real cloudapply takes the result of plan and actually calls the cloud API: it creates, changes, and deletes resources. After apply, the state is updated. This is the command that turns money into infrastructure.
  • tf-planterraform plan: see what Terraform is about to doplan is a dry run: Terraform reads your HCL, reads the state, and shows the diff between them. It changes nothing in the cloud. This is your main tool for not breaking prod by mistake.
  • tf-resource-lifecyclelifecycle: controlling resource behaviorThe lifecycle block configures four behaviors: create_before_destroy (zero-downtime replacement), prevent_destroy (deletion guard), ignore_changes (ignore drift on specific attributes), replace_triggered_by (force replacement on an external signal).
  • tf-destroyterraform destroy: tear down everything you createddestroy removes every resource described in HCL and recorded in state. It is apply with a minus sign in front of everything. It is essential for learning tasks and ephemeral environments. In production it is a last resort.
Footer
linuxlab-
Copyright © 2026 LinuxLab. All rights reserved.
Tutorials
Pricing
About
Privacy & cookies