Terraform Taint [Replace Resource]
Sometimes a resource goes sideways and Terraform loses track. Maybe an application inside a VM crashed while the VM itself keeps running. Or someone manually patched a database server outside of Terraform’s control. In these cases, you need to tell Terraform “this thing is broken, replace it” – and that is what taint is for.
One thing to get straight upfront: the terraform taint command is gone. HashiCorp deprecated it in v0.15.2 and removed it from the documentation entirely in later versions. The -replace flag on terraform apply is the replacement, and it works better anyway. I will cover that below.
What does “tainted” mean?
When a resource is marked as tainted, Terraform records that the object is in a degraded state. The next time you run terraform plan, you will see a proposal to destroy and recreate it. It does not happen immediately – you get to review the plan first.
When to use it
Taint comes up in a few situations:
- An application inside a VM crashed, but the VM itself keeps running. Terraform only manages the VM, not what runs inside it.
- Someone edited a server directly over SSH and made manual changes. Terraform does not know about those changes.
- A resource got into a state that Terraform cannot recover from automatically.
- You want to force a clean rebuild without changing any code.
How to find the resource address
List everything Terraform knows about:
terraform state list
You will see addresses like:
aws_instance.webserver[0]
aws_instance.webserver[1]
module.network.aws_subnet.example
The format is <type>.<name> for normal resources, or module.x.<type>.<name> for resources inside modules.
The current way: terraform apply -replace
terraform apply -replace="aws_instance.webserver[0]"
Or if you want to see the plan first:
terraform plan -replace="aws_instance.webserver[0]"
terraform apply -replace="aws_instance.webserver[0]"
This approach has a real advantage over the old taint command. With terraform taint, another team member could run their own plan before you apply and silently overwrite your taint decision. With -replace, the replacement shows up in the plan output immediately – everyone sees exactly what will happen before anyone commits to it.
Keeping the old resource while creating a new one
Here is a trick I have used a few times when I needed to replace a resource but wanted to keep the old one running for investigation.
Remove it from Terraform’s state:
terraform state rm aws_instance.webserver[0]
Terraform forgets about that instance. When you run terraform apply, it creates a fresh instance and leaves the old one untouched. You end up with both – the old one you can poke around in, and the new one taking over.
This works because terraform state rm only removes Terraform’s tracking. It does not touch the actual cloud resource.
Untainting: when Terraform is wrong
If Terraform has marked a resource as tainted but you know it is fine, you can override that:
terraform untaint aws_instance.webserver[0]
After running this, Terraform stops proposing to replace the resource. This is useful when you know something Terraform cannot detect – for example, a manually fixed application inside a VM.
Quick reference
| Task | Command |
|---|---|
| Force replacement | terraform apply -replace="<address>" |
| Remove from state | terraform state rm <address> |
| Remove taint status | terraform untaint <address> |
| List all resources | terraform state list |
What has changed since 2021
HashiCorp has fully deprecated terraform taint. The command still technically works in Terraform 1.x for now, but it is no longer documented and the plan output does not make it obvious that someone else previously marked a resource – which was a real problem in team environments. The -replace flag fixes this by making the replacement visible in the plan itself.
terraform state rm and terraform untaint remain unchanged and are still documented.
Bottom line
- Use
terraform apply -replace="resource_address"instead of the oldterraform taintcommand - Use
terraform state rmto keep a resource running but stop Terraform from managing it - Use
terraform untaintwhen Terraform is being overly cautious about a healthy resource - The
-replaceflag is the way forward. If you are still usingterraform taint, plan to switch – it will not be around forever
Comments