# terraform / lifecycle / guardrails

Control How Resources Live & Die: Resource Lifecycle

By default, when an argument change forces a resource replacement, Terraform destroys the old resource first and creates the new one — causing service downtime. The lifecycle meta-argument gives you fine-grained control to prevent accidental deletions, enable zero-downtime updates, and ignore external drift.

lifecycle { ... }GUARDRAIL
create_before_destroytrue (Zero Downtime)
prevent_destroytrue (DB Protection)
ignore_changes[tags, desired_count]
0s
Downtime
100%
Data Safety
No-Drift
Autoscaling
# default behavior

The Default Lifecycle & The Downtime Gap

When you change an immutable attribute on a cloud resource (like changing an EC2 instance's AMI, or recreating a security group), Terraform must replace the resource. Terraform's default sequence is Destroy Old → Create New.

Default Sequence (Downtime Gap)

1. Terminate Live Server
2. Service Outage Gap (3-5 min)
3. New Server Boots
solution

The lifecycle {} Block

Placed directly inside any resource block to customize how Terraform plans and applies operations against that specific cloud asset.

# zero downtime

1. create_before_destroy = true

main.tfZERO DOWNTIME PATTERN
1 2 3 4 5 6 7 8 9 10
resource "aws_instance" "web" {
  ami           = "ami-0123456789abcdef0"
  instance_type = "t3.micro"

  lifecycle {
    create_before_destroy = true
  }
}
execution order

Reverses the Creation Order

Terraform provisions the new resource first. Once the new resource is verified active and running, Terraform deletes the old one. This ensures zero downtime during web server and load balancer rolling replacements.

# data protection

2. prevent_destroy = true (Accident Guardrail)

rds.tfPROTECTED DATABASE
1 2 3 4 5 6 7 8 9 10 11
resource "aws_db_instance" "production_db" {
  allocated_storage = 100
  engine            = "postgres"
  instance_class    = "db.t3.large"
  db_name           = "production_data"

  lifecycle {
    prevent_destroy = true
  }
}
hard fail

Aborts Execution Plan Immediately

If anyone accidentally runs terraform destroy or edits a setting that requires database recreation, Terraform fails the plan step instantly with an error:

Error: Instance cannot be destroyed by Terraform
Resource has lifecycle.prevent_destroy set.
# drift control

3. ignore_changes: Stop Fighting External Tools

asg.tfIGNORING DYNAMIC ATTRIBUTES
1 2 3 4 5 6 7 8 9 10 11 12 13
resource "aws_autoscaling_group" "app_asg" {
  name             = "app-autoscaling"
  min_size         = 2
  max_size         = 10
  desired_capacity = 2

  lifecycle {
    # Ignore changes made by AWS Auto Scaling policies
    ignore_changes = [
      desired_capacity,
      tags
    ]
  }
}
anti-thrash

Why ignore_changes is Essential

During peak shopping hours, AWS Auto Scaling increases desired_capacity from 2 to 8. Without ignore_changes, running Terraform would see drift and force capacity back down to 2, causing an outage.

# dependencies

4. depends_on: Explicit Dependency Hints

s3_iam.tfEXPLICIT DEPENDS_ON
1 2 3 4 5 6 7 8 9 10 11 12 13 14
resource "aws_iam_role_policy_attachment" "s3_access" {
  role       = aws_iam_role.app.name
  policy_arn = "arn:aws:iam::aws:policy/AmazonS3FullAccess"
}

resource "aws_instance" "worker" {
  ami                  = "ami-0123456789abcdef0"
  instance_type        = "t3.micro"
  iam_instance_profile = aws_iam_instance_profile.app.name

  # Wait until IAM policy is attached before booting
  depends_on = [
    aws_iam_role_policy_attachment.s3_access
  ]
}
implicit vs explicit

When Terraform Needs a Hint

Normally Terraform infers dependencies implicitly by inspecting variable references (e.g. subnet_id = aws_subnet.web.id). When two resources have a hidden timing dependency that isn't referenced directly in arguments, use depends_on.

# cheat sheet

Lifecycle Arguments Reference

ArgumentValue TypeCore Purpose
create_before_destroyboolCreate replacement before terminating original (zero downtime).
prevent_destroyboolBlock destruction of critical databases or storage.
ignore_changeslist(attribute) or allPrevent Terraform from overwriting changes made by external systems.
replace_triggered_bylist(reference)Force recreation when an associated resource or configuration hash changes.
depends_onlist(resource)Enforce explicit DAG creation order before provisioning.