Crisp answer: The lifecycle block controls how Terraform creates, updates,
and destroys a specific resource. The four settings are create_before_destroy,
prevent_destroy, ignore_changes, and replace_triggered_by.
create_before_destroy:
resource "aws_instance" "web" {
ami = var.ami_id
instance_type = "t3.micro"
lifecycle {
create_before_destroy = true
}
}
Default Terraform behaviour on a resource that must be replaced: destroy the old resource first, then create the new one. This causes downtime.
With create_before_destroy = true: create the new resource first, then
destroy the old one. Requires that two instances of the resource can exist
simultaneously (most can).
Use for: EC2 instances behind an ALB, Launch Templates, ACM certificates.
prevent_destroy:
resource "aws_rds_cluster" "main" {
cluster_identifier = "prod-db"
lifecycle {
prevent_destroy = true
}
}
Terraform will refuse to destroy this resource even if you run terraform destroy or remove the block from config. Returns an error instead.
Use for: production databases, S3 buckets with irreplaceable data, anything where accidental deletion is catastrophic.
To actually destroy it: remove the prevent_destroy setting first, apply,
then destroy.
ignore_changes:
resource "aws_instance" "web" {
ami = var.ami_id
instance_type = "t3.micro"
tags = local.standard_tags
lifecycle {
ignore_changes = [
tags["LastDeployedBy"], # This tag is set by a deployment tool, not Terraform
user_data, # User data changes trigger replace — ignore to prevent
]
}
}
Terraform ignores these attributes when calculating diffs. If the real resource has a different value, no change is planned.
Use for: tags managed by other tools, auto-scaling group sizes managed by AWS, anything that drifts intentionally.
replace_triggered_by:
resource "aws_instance" "web" {
ami = var.ami_id
lifecycle {
replace_triggered_by = [
aws_launch_template.web.id, # Replace instance when the launch template changes
]
}
}
Force a replacement of this resource when another resource changes, even if this resource's own attributes haven't changed.
What to say in the interview:
"The lifecycle block fine-tunes how Terraform handles creates, updates, and destroys. The ones I use most: create_before_destroy for anything behind a load balancer so there's no downtime during replacement, and prevent_destroy on production databases to catch accidental deletes before they happen. ignore_changes is useful when something outside Terraform manages specific attributes — like a deployment tool writing a last-deployed tag. Without ignore_changes, every plan would show that tag as a diff Terraform wants to remove."