State & Workspaces
.mdVerified against Terraform v1.9.8, flags verified via `terraform <cmd> -help` run locally; taint-vs-replace guidance cross-checked against developer.hashicorp.com/terraform/cli docs (not executed against real infra), 2026-08-21 · official docs
Inspecting and surgically editing state, managing workspaces, importing existing infrastructure, and reading outputs.
Inspecting state#
terraform state list # every resource instance in state
terraform state list module.vpc # filter to one module
terraform state show aws_instance.web # full attributes of one resource, as currently in stateMoving and removing state entries#
terraform state mv aws_instance.old aws_instance.new # rename a resource without destroy/recreate
terraform state mv module.old_name module.new_name # move an entire module
terraform state rm aws_instance.web # forget a resource without destroying it in real infrastate rm does not touch the real infrastructure — it only makes Terraform stop tracking the resource. Useful when a resource should now be managed elsewhere (a different state file, or manually), but never a way to "delete" something you actually want gone.
Workspaces#
terraform workspace list
terraform workspace new staging
terraform workspace select staging
terraform workspace select production -or-create # switch, creating it first if it doesn't exist
terraform workspace show # print the currently-selected workspace's name
terraform workspace delete staging # delete a workspace (fails if it's managing resources)
terraform workspace delete -force staging # delete even if Terraform still thinks it manages resourcesWorkspaces give you multiple independent state files from one configuration — useful for environment isolation (dev/staging/prod) with the same code, but each workspace still shares the same backend config and provider credentials. For genuinely separate environments with different credentials/accounts, separate root modules (not workspaces) are the more common enterprise pattern.
${terraform.workspace} is available inside your .tf config to key off the current workspace name — e.g. count = terraform.workspace == "prod" ? 3 : 1 — but this couples your logic to workspace naming, which is easy to typo and has no built-in validation. For anything beyond a small dev/staging split, an explicit var.environment passed via -var-file is usually easier to reason about and review in a plan.
workspace delete -force unregisters the workspace's state from Terraform's bookkeeping — it does not destroy the real infrastructure that workspace was managing. Always terraform destroy in that workspace first if the infrastructure itself should also go away.
Importing existing infrastructure#
terraform import aws_instance.web i-0123456789abcdef0import only populates state — it does not generate the matching .tf configuration for you. You still have to hand-write a resource block that matches the imported object's real attributes, or the next plan will show a large diff trying to reconcile your (empty/wrong) config against the imported state.
Reading outputs#
terraform output # all outputs
terraform output instance_ip # a single output's value
terraform output -json # machine-readable, for piping into another tool/script
terraform output -raw instance_ip # raw string, no quotes — for shell scriptingForcing resource replacement#
terraform apply -replace=aws_instance.web # current recommended way to force a resource to be destroyed + recreated
terraform taint aws_instance.web # older command, still works — marks a resource tainted for the next plan
terraform untaint aws_instance.web-replace on plan/apply is the currently-documented approach (per official docs) for forcing replacement — taint/untaint still function in this version but are the older mechanism; prefer -replace in new scripts and runbooks.
Interactive console (for testing expressions)#
terraform consoleOpens a REPL that loads current state and lets you evaluate expressions/interpolations (e.g. aws_instance.web.public_ip) before committing them to a config file — read-only, never modifies state.
Inspecting resolved provider requirements#
terraform providers # tree of modules annotated with their provider requirements
terraform providers lock # write/refresh .terraform.lock.hcl for the constrained providers
terraform providers schema -json # full JSON schema for every provider used in the configproviders schema -json is mostly a building block for tooling (linters, policy checks, docs generators) rather than something you read directly — it dumps the complete resource/data-source attribute schema for every provider currently in use.