Terraform provides a suite of commands for inspecting and modifying state. These commands enable advanced workflows like refactoring, resource migration, and troubleshooting.
State manipulation commands directly modify your state file. Always backup state before performing destructive operations.
# Rename a resourceterraform state mv aws_instance.web aws_instance.app# Move to moduleterraform state mv aws_instance.web module.compute.aws_instance.web# Move from module to rootterraform state mv module.old.aws_instance.web aws_instance.web# Move between state filesterraform state mv -state-out=other.tfstate aws_instance.web aws_instance.web
// From internal/command/state_mv.go:274case addrs.AbsResourceInstance: addrTo, ok := destAddr.(addrs.AbsResourceInstance) if !ok { // Can convert AbsResource to AbsResourceInstance with NoKey ra, ok := destAddr.(addrs.AbsResource) if !ok { diags = diags.Append(tfdiags.Sourceless( tfdiags.Error, msgInvalidTarget, fmt.Sprintf("Cannot move %s to %s: the target must also be a resource instance.", addrFrom, destAddr), )) return 1 } addrTo = ra.Instance(addrs.NoKey) }
Supports moving both resources and individual instances.Reference: internal/command/state_mv.go:274-343
# Dry run - show what would happenterraform state mv -dry-run source destination# Disable lockingterraform state mv -lock=false source destination# Custom lock timeoutterraform state mv -lock-timeout=5m source destination# Move to different state fileterraform state mv -state-out=other.tfstate source destination# Use custom state pathsterraform state mv -state=old.tfstate -backup=old.backup source destination
# Remove single resourceterraform state rm aws_instance.web# Remove resource with countterraform state rm 'aws_instance.app[0]'# Remove entire moduleterraform state rm module.legacy# Remove multiple resourcesterraform state rm aws_instance.web aws_instance.app
// From internal/states/sync.go:316func (s *SyncState) ForgetResourceInstanceAll(addr addrs.AbsResourceInstance) { defer s.beginWrite()() ms := s.state.Module(addr.Module) if ms == nil { return } ms.ForgetResourceInstanceAll(addr.Resource) s.maybePruneModule(addr.Module)}
# Dry run - preview removalterraform state rm -dry-run aws_instance.web# Disable lockingterraform state rm -lock=false aws_instance.web# Custom backup pathterraform state rm -backup=custom.backup aws_instance.web# Use specific state fileterraform state rm -state=custom.tfstate aws_instance.web
# Move module instanceterraform state mv module.old module.new# Move nested moduleterraform state mv module.parent.module.child module.relocated
From the implementation:
// From internal/command/state_mv.go:183case addrs.ModuleInstance: search := sourceAddr.(addrs.ModuleInstance) addrTo, ok := destAddr.(addrs.ModuleInstance) if !ok { diags = diags.Append(tfdiags.Sourceless( tfdiags.Error, msgInvalidTarget, fmt.Sprintf("Cannot move %s to %s: the target must also be a module.", addrFrom, destAddr), )) return 1 }
// From internal/command/state_mv.go:352// Look for any dependencies that may be affected and// remove them to ensure they are recreated in full.for _, mod := range stateTo.Modules { for _, res := range mod.Resources { for _, ins := range res.Instances { if ins.Current == nil { continue } for _, dep := range ins.Current.Dependencies { if dep.TargetContains(rawAddrFrom) || rawAddrFrom.TargetContains(dep) { ins.Current.Dependencies = nil break } } } }}
Dependencies involving moved resources are cleared and rebuilt on next apply.Reference: internal/command/state_mv.go:352-372
# 1. Move resources to new structureterraform state mv aws_instance.old module.compute.aws_instance.new# 2. Update configuration to match# Edit .tf files# 3. Verify with planterraform plan # Should show no changes
# 1. Create new state fileterraform state mv -state-out=new.tfstate module.extracted module.extracted# 2. Configure new backend for extracted resources# 3. Initialize new backendcd extracted/terraform init
# Export from workspace Aterraform workspace select workspace-aterraform state pull > /tmp/resource.tfstate# Extract specific resourceterraform state mv -state=/tmp/resource.tfstate \ aws_instance.web \ -state-out=/tmp/extracted.tfstate# Import to workspace B terraform workspace select workspace-bterraform state push /tmp/extracted.tfstate