Reference · Terraform

The Modern Workflow

Config-driven lifecycle ops, plan-as-artifact, drift detection — how teams actually run Terraform in 2025+.

The config-driven lifecycle trio

Three declarative blocks replaced three imperative CLI commands. Same state surgery — but reviewable in a PR, previewable in a plan, replayable anywhere.

Block (since)ReplacesDoes
moved (1.1)terraform state mvRename/move an address without destroy+create
import (1.5)terraform importAdopt an existing real resource into state
removed (1.7)terraform state rmForget a resource — stop managing, keep it alive
import {
  to = aws_s3_bucket.legacy
  id = "acme-legacy-data"
}
# then: terraform plan -generate-config-out=generated.tf  ← drafts the resource block for you

removed {
  from = aws_db_instance.old
  lifecycle { destroy = false }   # forget, don't destroy (omit destroy=false at your peril)
}

Sources: import + config generation · removed block · 1.7 announcement

The team loop (PR-driven)

# local / pre-commit
terraform fmt -check     # canonical formatting
terraform validate       # syntax + internal consistency, no cloud calls
terraform test           # unit layer: plan-mode + mocks

# CI on PR
terraform plan -out=tfplan       # the plan IS the artifact…
# …human reviews the plan output, approves…

# CI on merge/approval
terraform apply tfplan           # apply EXACTLY what was reviewed — not a fresh plan
Why apply the saved plan? Re-planning at apply time means applying something nobody reviewed (the world may have changed in between). apply tfplan executes the reviewed change set exactly — if reality drifted since, the apply errors instead of improvising. That's the same three-pictures logic from lesson 0001, weaponized for CI.

Source: Running Terraform in automation

Drift detection on a schedule

terraform plan -detailed-exitcode   # 0 = clean · 1 = error · 2 = changes pending
# cron/nightly: exit 2 → page the channel; review with plan -refresh-only to see pure drift

Versions, pins, and the fork