DevOpsLesson
DevOpsLesson

Free, comprehensive DevOps tutorials and learning roadmaps. Master Docker, Kubernetes, CI/CD, and more.

Stay Updated

Get notified about new tutorials and features.

Tutorials

  • What is DevOps?
  • Docker Tutorial
  • Terraform Tutorial
  • CI/CD Pipeline
  • All Tutorials

Roadmaps

  • DevOps Engineer
  • Cloud Engineer
  • SRE Path
  • All Roadmaps

Company

  • About Us
  • Blog
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 DevOpsLesson. All rights reserved.

DOCKERKUBERNETESTERRAFORMAWSCI/CDLINUXGITDEVOPS ROADMAPCLOUD ROADMAPSRE ROADMAPGIT CHEATSHEETDOCKER CHEATSHEETK8S CHEATSHEETTF CHEATSHEETLINUX CHEATSHEETDOCKERFILE LINTERYAML VALIDATORCRON PARSERREGEX TESTER

Terraform Tutorial

Introduction to Terraform
Installing Terraform
The Terraform Core Workflow
Terraform Variables and Outputs
Terraform State and Backends
Terraform Modules
Terraform Data Sources
Terraform Count and for_each
Terraform Expressions and Functions
Terraform Dynamic Blocks
Terraform Workspaces
Terraform with AWS
Terraform Provisioners
Terraform CI/CD Pipeline
Terraform Security

Terraform State Commands

PreviousPrev
Next

Learn the most important Terraform state and import commands, including terraform state list, show, mv, rm, import, and refresh-related workflows.

Why Terraform State Commands Exist

Most of the time, Terraform updates state automatically. You run terraform plan and terraform apply, and Terraform handles the internal bookkeeping for you.

But real infrastructure projects are messy. Resource names change. Modules get reorganized. Existing cloud resources need to be brought under Terraform management. Sometimes you need to inspect state directly to understand what Terraform thinks it owns.

That is where Terraform state commands come in.

These commands let you inspect or carefully adjust Terraform's record of managed infrastructure without always changing the actual cloud resources themselves.

This is powerful, but it also means you must use these commands with care. Many of them affect Terraform's memory of infrastructure, not the infrastructure itself.

When Should You Use State Commands?

State commands are most useful when you need to:

  • inspect what Terraform currently manages
  • examine the stored attributes of a resource
  • rename or move resource addresses after refactoring code
  • stop Terraform from managing a resource without deleting it
  • import existing infrastructure into Terraform
  • refresh Terraform's understanding of real infrastructure

For day-to-day Terraform usage, you may not need them often. But when you do need them, they are essential.

terraform state list

The terraform state list command shows all resource addresses currently tracked in state.

terraform state list

Example output:

aws_vpc.main
aws_subnet.public[0]
aws_subnet.public[1]
aws_internet_gateway.main
aws_security_group.web
aws_instance.web
module.network.aws_route_table.public

Why terraform state list is useful

This command answers the question: What does Terraform think it manages right now?

That is helpful when:

  • debugging unexpected plans
  • exploring a large module-based configuration
  • preparing to move or remove a resource from state
  • checking whether a resource was imported successfully

Practical example

Suppose you refactored code and Terraform says a resource will be destroyed and recreated. terraform state list can help you confirm the existing state address before using terraform state mv.

terraform state show

The terraform state show command prints the state details for a single resource.

terraform state show aws_instance.web

Example output might include:

# aws_instance.web:
resource "aws_instance" "web" {
    ami                         = "ami-0abcdef1234567890"
    arn                         = "arn:aws:ec2:us-east-1:123456789012:instance/i-0123456789abcdef0"
    associate_public_ip_address = true
    id                          = "i-0123456789abcdef0"
    instance_type               = "t3.micro"
    private_ip                  = "10.0.1.24"
    public_ip                   = "54.12.34.56"
}

Why terraform state show is useful

state show helps you inspect what Terraform currently knows about a resource.

Common uses:

  • checking resource IDs
  • verifying tag values
  • confirming subnet associations
  • seeing whether a provider attribute exists in state
  • troubleshooting why Terraform wants to change something

Important note

This is state data, not necessarily a complete live API response from the provider at that exact second. It reflects Terraform's recorded or refreshed view.

terraform state mv

The terraform state mv command changes a resource's address in the state file.

It does not recreate the cloud resource. It tells Terraform, “This existing object should now be tracked under a different address.”

Basic syntax

terraform state mv aws_instance.web aws_instance.app

Common use case: renaming a resource

Imagine you rename this resource in code:

resource "aws_instance" "web" {

to:

resource "aws_instance" "app" {

If you do nothing, Terraform sees:

  • aws_instance.web is gone -> destroy it
  • aws_instance.app is new -> create it

That is not what you want. It is the same real instance; only the logical Terraform name changed.

So you run:

terraform state mv aws_instance.web aws_instance.app

Now Terraform tracks the same real instance under the new address.

Another use case: moving into a module

Suppose a resource used to live in the root module:

aws_security_group.web

After refactoring, it now belongs inside a module:

module.network.aws_security_group.web

You can move the state address:

terraform state mv aws_security_group.web module.network.aws_security_group.web

This is extremely useful during code refactoring.

terraform state rm

The terraform state rm command removes a resource from Terraform state without destroying the actual infrastructure object.

Syntax

terraform state rm aws_instance.web

After this command:

  • the EC2 instance still exists in AWS
  • Terraform no longer tracks it in state

Why would you use this?

Common scenarios include:

  • you want Terraform to stop managing a resource
  • you need to detach an object before handing it to another system
  • state is wrong and you plan to re-import the resource cleanly
  • a resource was created manually and is better managed elsewhere

Important warning

state rm only changes Terraform's memory. It does not delete the real object.

That sounds safe, but it can cause confusion. If the configuration still contains the resource block, the next terraform plan may try to create a new resource because Terraform no longer sees the old one in state.

So use state rm intentionally and understand what the next plan will do.

terraform import

terraform import brings an existing real infrastructure object under Terraform management by associating it with a resource address in state.

This is crucial when resources already exist before Terraform is introduced.

Example

Suppose an S3 bucket already exists in AWS:

  • bucket name: company-audit-logs

You write the Terraform resource block first:

resource "aws_s3_bucket" "audit_logs" {
  bucket = "company-audit-logs"
}

Then import it:

terraform import aws_s3_bucket.audit_logs company-audit-logs

Now Terraform tracks that bucket in state.

Why import matters

Many real environments are not built from scratch. They contain existing networks, buckets, IAM roles, or databases. Import lets Terraform adopt them gradually.

Important detail

Import adds the object to state, but you still need your configuration to match the real resource accurately. After importing, run terraform plan and expect to refine the .tf code until Terraform no longer shows unexpected changes.

terraform refresh

Historically, terraform refresh updated state to reflect the current real infrastructure without changing resources.

terraform refresh

What it does conceptually

Terraform queries the provider APIs, reads current infrastructure details, and updates the state accordingly.

Why it matters

This can help when you suspect drift or when you want Terraform's stored view to reflect the latest real-world information.

Modern caution

In modern Terraform workflows, many teams prefer terraform plan or terraform apply -refresh-only because they make refresh behavior more explicit and easier to review. But it is still important to understand the refresh concept because state must periodically be reconciled with reality.

Beginner takeaway

Think of refresh as: update Terraform's state to match what exists right now.

When to Use Each Command

Here is a practical summary.

CommandUse it when...
terraform state listYou want to see every resource Terraform currently tracks
terraform state showYou want detailed stored attributes for one resource
terraform state mvYou refactored resource addresses and need to keep the same real object
terraform state rmYou want Terraform to forget a resource without deleting it
terraform importA real resource exists already and must be brought under Terraform management
terraform refreshYou want state updated to reflect real infrastructure, or you want to understand refresh behavior

Refactoring Example: Rename Without Recreate

Imagine this original resource:

resource "aws_security_group" "web" {
  name = "web-sg"
}

Later, you realize app is a better name:

resource "aws_security_group" "app" {
  name = "web-sg"
}

If you run terraform plan immediately, Terraform may want to destroy and recreate the security group. To preserve the existing object, you use:

terraform state mv aws_security_group.web aws_security_group.app

This tells Terraform the object already exists; only the address changed.

Reorganizing into Modules

State commands become even more valuable when you modularize Terraform.

Suppose a subnet resource used to live at:

aws_subnet.public[0]

After creating a child module, the new address becomes:

module.network.aws_subnet.public[0]

Instead of recreating the subnet, you move the state address:

terraform state mv aws_subnet.public[0] module.network.aws_subnet.public[0]

That preserves the actual infrastructure while aligning state with the new code structure.

Import Workflow Example

A realistic import workflow often looks like this:

  1. identify an existing resource in the cloud
  2. write a Terraform resource block for it
  3. run terraform import
  4. run terraform plan
  5. update the code until the plan is clean or intentionally understood

For example, importing an existing security group:

terraform import aws_security_group.web sg-0123456789abcdef0

After import, Terraform knows about the security group, but your code may still be incomplete. Maybe ingress rules or tags differ. The follow-up terraform plan reveals that gap.

Common Risks and Mistakes

Using state commands casually

State commands are not everyday formatting tools. They change Terraform's understanding of infrastructure. Always know why you are running one.

Forgetting to back up or rely on remote backend safeguards

State changes can be disruptive if done incorrectly. In production, versioned remote state and locking are valuable safety nets.

Running state rm but leaving the resource block in code

Terraform may then plan to recreate the resource because it still appears in configuration.

Importing without matching the configuration

Import only updates state. It does not automatically write perfect .tf code for you. Expect to reconcile the configuration afterward.

Assuming state show is a live API browser

It shows Terraform's current recorded information, not necessarily a complete real-time console replacement.

Best Practices for State Commands

  1. Use remote backends with versioning and locking in team environments.
  2. Run terraform plan before and after significant state operations.
  3. Use state mv during refactors to avoid unnecessary recreation.
  4. Use state rm only when you intentionally want Terraform to forget an object.
  5. After imports, refine configuration until the plan is understood.
  6. Prefer reviewable refresh workflows in modern Terraform usage.
  7. Treat state operations as high-impact changes.

Final Thoughts

Terraform state commands are the advanced toolbox for managing Terraform's memory of infrastructure. They are not needed every day, but they become invaluable when you refactor code, adopt existing resources, or debug what Terraform thinks it owns.

A simple way to remember them is:

  • state list shows what Terraform tracks
  • state show shows what Terraform knows about one object
  • state mv changes where Terraform tracks it
  • state rm makes Terraform forget it
  • import helps Terraform adopt it
  • refresh helps Terraform reconcile state with reality

Used carefully, these commands let you evolve Terraform code without unnecessary destruction and bring existing infrastructure under consistent management.


Knowledge Check

Exercise

Question 1: state mv

When is terraform state mv most useful?

Exercise

Question 2: state rm

What happens when you run terraform state rm aws_instance.web?

Exercise

Question 3: import

What is the main purpose of terraform import?

PreviousPrev
Next

Continue Learning

Terraform State and Backends

Learn the big picture of Terraform state, remote backends, and state management commands so you can work safely with real infrastructure and collaborate with confidence.

5 min read·Medium

Terraform State Overview

Learn what Terraform state is, why the terraform.tfstate file exists, how it maps to real infrastructure, and why state security and locking matter in production.

12 min read·Medium

Terraform Remote Backends

Learn why Terraform remote backends matter, how to configure S3 with DynamoDB locking, when to use Terraform Cloud or GCS, and how to migrate state safely.

12 min read·Medium

Explore Related Topics

AW

AWS Tutorials

Provision AWS infrastructure with Terraform

CI

CI/CD Tutorials

Run terraform plan/apply in CI pipelines

Try the Tool

YAML Validator

Validate Terraform and Kubernetes YAML configs before applying.

On This Page

Why Terraform State Commands ExistWhen Should You Use State Commands?`terraform state list`Why terraform state list is usefulPractical example`terraform state show`Why terraform state show is usefulImportant note`terraform state mv`Basic syntaxCommon use case: renaming a resourceAnother use case: moving into a module`terraform state rm`SyntaxWhy would you use this?Important warning`terraform import`ExampleWhy import mattersImportant detail`terraform refresh`What it does conceptuallyWhy it mattersModern cautionBeginner takeawayWhen to Use Each CommandRefactoring Example: Rename Without RecreateReorganizing into ModulesImport Workflow ExampleCommon Risks and MistakesUsing state commands casuallyForgetting to back up or rely on remote backend safeguardsRunning `state rm` but leaving the resource block in codeImporting without matching the configurationAssuming `state show` is a live API browserBest Practices for State CommandsFinal ThoughtsKnowledge Check