Quick Answer
# Modern way (Terraform 1.0+) — recommended
terraform apply -replace="aws_instance.web"
# Legacy way (deprecated but still works)
terraform taint aws_instance.web
terraform apply
Both force Terraform to destroy and recreate a resource on the next apply.
terraform taint vs terraform apply -replace
terraform taint was the original command. As of Terraform v1.0, terraform apply -replace is the recommended alternative:
terraform taint | terraform apply -replace | |
|---|---|---|
| Status | Deprecated (still works) | Recommended |
| Steps | Two commands (taint + apply) | One command |
| Plan preview | No (modifies state immediately) | Yes (shows plan first) |
| Undo | terraform untaint | Cancel the plan |
| State modification | Modifies state before apply | Only modifies during apply |
Using terraform apply -replace (Recommended)
Basic Usage
# Preview the replacement
terraform plan -replace="aws_instance.web"
# Apply the replacement
terraform apply -replace="aws_instance.web"
Output:
# aws_instance.web will be replaced, as requested
-/+ resource "aws_instance" "web" {
~ id = "i-0abc123def456" -> (known after apply)
~ public_ip = "54.123.45.67" -> (known after apply)
# (other attributes unchanged)
}
Plan: 1 to add, 0 to change, 1 to destroy.
Replace Multiple Resources
terraform apply \
-replace="aws_instance.web" \
-replace="aws_security_group.web"
Resources in Modules
terraform apply -replace="module.vpc.aws_subnet.public[0]"
Resources with count or for_each
# count index
terraform apply -replace="aws_instance.web[0]"
terraform apply -replace="aws_instance.web[2]"
# for_each key
terraform apply -replace='aws_instance.web["us-east-1"]'
Using terraform taint (Legacy)
Taint a Resource
terraform taint aws_instance.web
Output:
Resource instance aws_instance.web has been marked as tainted.
Verify the Taint
terraform plan
# aws_instance.web is tainted, so must be replaced
-/+ resource "aws_instance" "web" {
Apply the Replacement
terraform apply
Untaint (Undo)
Changed your mind? Remove the taint before applying:
terraform untaint aws_instance.web
Taint Resources in Modules
terraform taint module.webserver.aws_instance.app
terraform taint 'module.webserver.aws_instance.app[0]'
When to Force-Replace Resources
1. Resource Is in a Bad State
The EC2 instance is running but the application crashed and won’t recover:
terraform apply -replace="aws_instance.app"
Faster than SSH debugging if you have proper user_data/AMI setup.
2. Update Immutable Attributes
Some attributes can’t be changed in place (AMI, launch template). Terraform normally handles this, but if you need to force it:
terraform apply -replace="aws_launch_template.app"
3. Rotate Secrets or Certificates
Force recreation of resources that embed secrets:
terraform apply -replace="aws_iam_access_key.deploy"
terraform apply -replace="tls_private_key.ca"
4. Test Your Provisioning
Verify that your user_data, provisioners, or bootstrap scripts still work:
terraform apply -replace="aws_instance.web"
5. Force Null Resource Triggers
resource "null_resource" "deploy" {
triggers = {
version = var.app_version
}
provisioner "local-exec" {
command = "./deploy.sh"
}
}
terraform apply -replace="null_resource.deploy"
What Happens During Replacement
1. Terraform creates a plan showing the resource will be replaced
2. You approve the plan
3. Terraform DESTROYS the existing resource
4. Terraform CREATES a new resource with the same configuration
5. State is updated with the new resource ID
Important: The default order is destroy-then-create. If you need create-before-destroy (zero downtime), add a lifecycle rule:
resource "aws_instance" "web" {
# ...
lifecycle {
create_before_destroy = true
}
}
Risks and Precautions
Data Loss
Replacing a resource destroys it. If it has data (EBS volume, database, S3 bucket), that data may be lost:
# DANGEROUS — will destroy the database!
terraform apply -replace="aws_db_instance.production"
Always check what happens to data before replacing stateful resources.
Downtime
Between destroy and create, the resource doesn’t exist. For production services, use create_before_destroy or blue-green deployments.
Dependent Resources
Replacing a resource may trigger changes in dependent resources:
terraform plan -replace="aws_security_group.web"
# Shows:
# aws_security_group.web will be replaced
# aws_instance.web will be updated (security group reference changes)
Always review the full plan before applying.
State Lock
If you’re using remote state, ensure no one else is running Terraform at the same time:
# Check current state lock
terraform force-unlock LOCK_ID # Only if stuck
Common Errors
“Resource instance not found”
Error: Resource instance aws_instance.web not found in the current state.
The resource doesn’t exist in state. Check with terraform state list.
“Cannot taint a resource within a module”
Use the full module path:
terraform taint module.app.aws_instance.web
# NOT
terraform taint aws_instance.web # Wrong if it's in a module
Taint + prevent_destroy conflict
Error: Instance cannot be destroyed
The resource has prevent_destroy = true. Remove it first, or use -replace which shows this in the plan.
Hands-On Courses
Learn by doing with interactive courses on CopyPasteLearn:
Conclusion
Use terraform apply -replace="resource.name" to force-recreate resources. It’s the modern replacement for terraform taint — one command, with a plan preview, no premature state modification. Use it for broken instances, secret rotation, immutable attribute updates, and provisioning tests. Always review the plan for data loss and downtime risks before applying.




