CertGrid
Terraform

Terraform Import, Moved, and Removed Blocks: Choose the Right State Change

By CertGrid TeamPublished 4 min read

TerraformDevOpsStudy Strategy

A resource already exists, but its Terraform configuration needs to change. Should you import it, move it, or remove it? The answer depends on what Terraform already manages and what should remain under management afterward. The same-looking cloud resource can require a different operation in a different state.

These are separate configuration examples, not a sequence to run. Confirm support in your installed Terraform version and the relevant provider documentation. Use a disposable study environment and review the plan before any apply. No infrastructure was created or changed to produce this article.

Describe the intended binding first

Three different Terraform management transitions
IntentStarting pointBlock to consider
Adopt an existing objectThe object exists but is not bound to this resource address in stateimport
Rename or reorganize a managed objectState already tracks it at an old addressmoved
Stop managing an object but retain itState tracks it, but ownership is being handed offremoved with destroy = false

State records which remote object is associated with each managed resource instance. Before making a change, establish the backend, workspace, provider account, and current resource address. A correct block against the wrong state can still be the wrong operation. Do not manually edit the state JSON to make an unexpected plan look smaller.

Use import to adopt an existing object

A configuration-driven import identifies an existing object and the Terraform address that should manage it. The resource type's provider documentation defines its import identifier. You also need the corresponding resource configuration, whether you write it or use supported configuration generation and review the result.

import {
  to = aws_s3_bucket.logs
  id = "replace-with-existing-bucket-name"
}

This example assumes the AWS provider's S3 bucket import identifier, an existing bucket, and an appropriate aws_s3_bucket.logs resource declaration. It is not a complete configuration. Importing the object does not mean every configured attribute already matches it: inspect the plan for additional changes rather than treating adoption as automatically change-free.

Before approval, write down the real object, its intended address, and the team that owns it. Check whether another state already manages it. A handover needs coordination; importing an object into a second configuration is not a substitute for agreeing which configuration is authoritative.

Use moved to preserve identity during a refactor

Suppose the existing address is aws_s3_bucket.logs and the configuration now calls it aws_s3_bucket.audit_logs. A moved block records that address transition, allowing Terraform to associate the existing object with the new name rather than interpreting the rename as an unrelated removal and creation.

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

Update the resource declaration and references consistently. A move is not a promise that no other changes will occur: attribute changes in the same revision may still propose updates or replacement. Review those separately. For reusable modules, retaining earlier moved blocks can preserve upgrade paths for users who have not yet applied an intermediate version.

Use removed carefully when handing off ownership

Deleting a resource declaration is not a safe shorthand for 'leave the object alone'. For an intentional handoff, a removed block can explicitly tell Terraform to stop managing the object without destroying it. The lifecycle setting matters because removal otherwise defaults to destruction.

removed {
  from = aws_s3_bucket.legacy_logs

  lifecycle {
    destroy = false
  }
}

In this separate example, replace the old resource declaration with the removed block and resolve references that depended on it. Review the plan for the intended management removal. The retained object still needs an owner, access controls, monitoring, and a cost decision. Leaving Terraform state is not equivalent to retiring the service.

Review the transition, not just the block name

  1. Before: identify the real object and whether this state already manages it.
  2. After: state the desired address or the new management owner.
  3. Proposal: inspect the plan for imports, address moves, removals, and unrelated infrastructure changes.
  4. Evidence: record the provider's import rules or the relevant language behavior alongside the change.
  5. Handoff: confirm who approves the change and who owns the object afterward.

For study, try three variations of one scenario: the object was created manually; the object is already managed under an older name; or another team is taking over management. Explain the difference without first naming a command. Then identify what evidence is missing before any change could be approved.

If the plan disagrees with that explanation, stop and use the unexpected Terraform plan checklist. Keep state and plan artifacts out of public repositories and support threads. The Terraform Associate study guide connects these state decisions to the wider workflow.

Official sources

Read next

Keep practicing on CertGrid

CertGrid is not affiliated with or endorsed by Microsoft, AWS, Google, Cisco, CompTIA, the Linux Foundation, HashiCorp, or other certification vendors. Questions are original practice items designed to mirror certification concepts and exam style. CertGrid does not provide official exam questions or braindumps.

Browse practice exams · Pricing · Study guides