Terraform Taint Explained: When to Use Taint vs Replace

Published: 2025-09-02
7 min read
Share:

Most Terraform users encounter tainted resources after a failed deployment and immediately wonder why Terraform wants to destroy and recreate infrastructure that already exists.

This Terraform taint guide explains how tainted resources work, what causes resources to become tainted, and why modern Terraform workflows often use terraform apply -replace instead. Understanding the difference helps prevent unnecessary downtime and reduces the risk of unexpected infrastructure changes.

If you're new to Terraform, start with our guide on Getting Started with Terraform on AWS before diving into advanced resource lifecycle management.

What Is Terraform Taint and How Does It Work?

Terraform uses its state file to track infrastructure resources and determine whether they match the desired configuration.

A resource is considered tainted when Terraform determines it may not be in a reliable or fully configured state. Once marked as tainted, Terraform plans to destroy and recreate that resource during the next apply operation.

Terraform stores this information in the state file. If you're unfamiliar with state management, read our guide on Introduction to Terraform State.

Historically, Terraform provided the terraform taint command to manually mark resources for replacement. While the command still exists in some older workflows, modern Terraform usage generally favors the -replace option during planning and apply operations.

Common Reasons a Resource Becomes Tainted

Resources typically become tainted for one of the following reasons:

Failed Provisioner Execution

Provisioners such as local-exec and remote-exec run commands after resource creation.

If the underlying resource is created successfully but the provisioner fails, Terraform may mark the resource as tainted because it cannot guarantee the resource was configured correctly.

For example:

  • An EC2 instance launches successfully.
  • A remote-exec script installs software.
  • The installation script fails halfway through.
  • Terraform treats the instance as potentially inconsistent.

If you're using provisioners extensively, review our guide on Terraform Provisioners and Provisioner Considerations.

Manual Resource Recreation

In older Terraform workflows, engineers sometimes manually marked resources as tainted when they wanted Terraform to rebuild them.

Typical scenarios included:

  • Configuration drift
  • Corrupted virtual machines
  • Failed software installation
  • Unrecoverable operating system issues

Partial Infrastructure Failures

Sometimes a cloud provider reports successful resource creation even though dependent configuration steps fail.

In these situations, replacing the resource is often safer than attempting manual repairs.

Terraform Taint Command Syntax

The traditional syntax looks like this:

terraform taint aws_instance.web_server

This command marks the resource as tainted within the Terraform state.

When you run:

terraform plan

Terraform shows that the resource will be destroyed and recreated.

After applying:

terraform apply

Terraform replaces the resource with a newly created instance.

Because the replacement is not immediately visible during the taint operation itself, many teams now prefer using -replace instead.

Terraform Apply -Replace: The Modern Alternative

Current Terraform documentation recommends using the -replace option because the replacement action becomes visible in the execution plan.

Instead of:

terraform taint aws_instance.web_server
terraform apply

Use:

terraform apply -replace="aws_instance.web_server"

You can also review the plan first:

terraform plan -replace="aws_instance.web_server"

Benefits of -replace include:

  • Clear visibility in the execution plan
  • Easier change reviews
  • Better CI/CD integration
  • Reduced risk of accidental replacements
  • Improved auditability

You can learn more in the official Terraform CLI Documentation.

How to Remove a Tainted Resource State

In environments that still use tainting workflows, Terraform provides the untaint command.

terraform untaint aws_instance.web_server

This removes the tainted flag and prevents Terraform from replacing the resource during the next apply operation.

Example:

terraform untaint aws_instance.web_server

Use this carefully. If the resource is genuinely broken or partially configured, removing the taint may leave infrastructure issues unresolved.

Example: Recovering From a Failed EC2 Provisioning Step

Consider an EC2 instance that uses a local-exec provisioner.

resource "aws_instance" "web_server" {
  ami           = "ami-xxxxxxxx"
  instance_type = "t3.micro"

  provisioner "local-exec" {
    command = "echo ${self.public_ip} >> /invalid/path/server.txt"
  }
}

The EC2 instance launches successfully.

However, the provisioner fails because the destination directory does not exist.

At this point:

  • The EC2 instance exists.
  • The provisioning step failed.
  • Terraform cannot guarantee the server is fully configured.
  • Terraform may mark the resource as tainted.

The next apply operation replaces the instance and attempts the provisioning process again.

Without replacement, you could end up with infrastructure that appears healthy but is missing critical configuration steps.

Production Considerations Before Replacing Resources

Resource replacement is not always harmless.

Replacing a stateless web server is usually straightforward. Replacing stateful infrastructure can have significant consequences.

Always review the impact before applying changes to:

  • Databases
  • Persistent volumes
  • Storage buckets
  • Stateful Kubernetes workloads
  • Message queues

Review the execution plan carefully and understand what Terraform intends to destroy before approving the change.

Terraform Taint Best Practices for Production Environments

Prefer Replace Over Taint

For modern Terraform versions, use:

terraform apply -replace="resource.address"

This provides better visibility and aligns with current Terraform recommendations.

Reduce Dependency on Provisioners

Provisioners should generally be a last resort.

Where possible, use:

  • Cloud-init
  • EC2 user data
  • Kubernetes manifests
  • Configuration management tools
  • Managed cloud services

Our guide on Terraform Provisioner Behaviour explains why provisioners can introduce operational complexity.

Review Terraform State Regularly

Understanding state helps you troubleshoot unexpected replacements and lifecycle behavior.

Helpful resources:

Validate Changes in CI/CD

Many engineering teams avoid manual tainting entirely.

Instead, they:

  1. Generate a plan.
  2. Review the proposed replacement.
  3. Approve the change.
  4. Apply using CI/CD pipelines.

This approach improves visibility and reduces human error.

Terraform Taint and Infrastructure Drift

Infrastructure drift occurs when actual infrastructure differs from Terraform configuration.

Examples include:

  • Manual server changes
  • Security group updates in the cloud console
  • Direct database modifications
  • Changes made outside Terraform workflows

Before replacing resources, investigate whether drift exists.

Useful references:

Frequently Asked Questions

What is Terraform taint used for?

Terraform taint marks a resource for destruction and recreation during a future apply operation when Terraform determines the resource may be unreliable or inconsistent.

Is Terraform taint deprecated?

HashiCorp recommends using terraform apply -replace for most replacement scenarios because it makes the replacement action explicit within the execution plan.

Does terraform taint delete resources immediately?

No.

The command only marks the resource for replacement. Actual destruction and recreation occur during a later apply operation.

How can I identify tainted resources?

Run:

terraform plan

Terraform displays resources scheduled for replacement.

You can also inspect state information using various Terraform state commands.

What is the difference between taint and replace?

terraform taint marks a resource in state and requires a later apply.

terraform apply -replace performs the replacement through the planning workflow, making the action visible and easier to review.

Does taint modify the Terraform state file?

Yes.

Terraform stores taint information in state so it can determine replacement actions during future plans and applies.

Should I replace resources after every provisioner failure?

Not always.

Investigate the root cause first. If the resource is fully functional and the failed step is non-critical, replacement may not be necessary. If the failure leaves the resource partially configured, replacement is usually the safer option.

Key Takeaways

  • Terraform taint marks resources for replacement.
  • Failed provisioners are a common cause of tainted resources.
  • Modern Terraform workflows generally favor terraform apply -replace.
  • Always review execution plans before approving replacements.
  • Be especially cautious when replacing stateful infrastructure.
  • Understanding Terraform state is essential for troubleshooting replacement behavior.

For deeper Terraform knowledge, explore:

Free Engineering ToolsNEW

8 free, 100% client-side tools for developers — no signup, no data uploads.

Explore all tools