Pro ยท Lesson 8 of 12

Lifecycle, import, moved, and removed

These blocks tell Terraform how to treat an object that already exists or that you renamed. They do not all exist on every old binary.

Sign in to save your place.

Picture it this way

import is writing an existing locker into the notebook. moved is changing the name in the notebook without throwing the contents away. removed is taking a line out of the notebook, and you must say whether the locker itself gets emptied.

lifecycle

prevent_destroy makes a plan fail instead of destroying that resource. create_before_destroy makes the new object first, which matters when a name must not have a gap. ignore_changes tells Terraform to leave listed arguments alone. Use it when something outside Terraform edits that field on purpose. It is also how drift hides. Review it.

replace_triggered_by replaces the object when another object changes. It is a lifecycle argument, not a cloud feature.

import, moved, and removed

An import block, added in Terraform 1.5, declares that an existing object should be recorded under an address. terraform plan -generate-config-out can draft HCL. Read the draft. Generated config is a start, not a style guide.

A moved block tells Terraform a rename. Without it, the plan destroys the old address and creates the new one. That is a real outage for a database.

A removed block, added in Terraform 1.7, drops an address from state. lifecycle { destroy = false } keeps the real object and forgets it. The default destroys it. Read the block before you apply.

OpenTofu started from code that already had import and moved. Later blocks and flags have diverged. The OpenTofu language page for your binary is the check. Do not copy a Terraform 1.10 snippet onto an old tofu and assume the keyword exists.

Block You want If you skip it
import Adopt an existing object Terraform offers to create a second one
moved Rename an address Destroy and create
removed Stop managing an object The next plan may still try to manage it

Rename without destroy

  1. Old address
  2. moved
  3. New address

Step 1 of 3The state still has the old address.

Lab: read a moved block before you need one

Do not apply this against a real bucket. The point is the shape of the block.

moved {
  from = module.storage.aws_s3_bucket.logs
  to   = module.storage.aws_s3_bucket.audit_logs
}

removed {
  from = aws_instance.abandoned_lab
  lifecycle {
    destroy = false
  }
}

Concept summary

Knowledge check

You rename a resource address and do not add a moved block. What does the plan want?

removed with destroy = false does what?

An OpenTofu binary rejects a block you copied from a new Terraform guide. Why might that be fair?

Official sources

Checked against the linked documentation in October 2026. A later release can move a flag, a price, or a supported pair. Use the page for the version you installed.