Master Terraform State - What Every Engineer Must Know
Master Terraform state with essential commands every engineer needs. Learn how to import, move, remove, unlock, backup, and restore your state safely!
Mastering Terraform State Management: Learn to Recover from Disasters!
Effectively managing Terraform state is essential for maintaining reliable infrastructure as code workflows. In large enterprise environments, knowing how to modify and recover the state file during unforeseen issues is critical to keeping your deployments consistent, secure, and operational.
In this guide, we’ll walk through importing resources, moving resources, removing resources, unlocking state, and backing up or restoring state using the Terraform CLI, Azure CLI, and the Azure Portal.
We’ll cover all the common methods to ensure you’re comfortable managing, troubleshooting, and restoring Terraform state when needed.
Generally when you run a terraform command that involves writing to state like an apply, the state file is locked to avoid any other modifications.
A graceful shutdown was not successful and the state file lock was not released.
1. Backup and Restore State
Note: You should always have a backup of your state file and its always best practice to take a backup before you make significant changes to state including performing any upgrades.
You can use the Terraform CLI to directly pull down a copy of your state file. Please keep in mind if you have your Terraform state stored in a remote storage account, that you will need to have network connectivity and permissions to the blob container (or S3 bucket) from where you are running the command.
In an Enterprise environment, you made not have direct access to the storage account, so here are some options:
Use Azure Portal to manually download the state file
Enable Blob versioning on the Terraform state blob container
Execute the commands from a build agent
# Terraform CLI
Backup State
To save a local copy of the current state, use the following commands.
terraform init
terraform state pull > backup.tfstate
Restore State
First you need to edit the file backup.tfstate in Notepad or VSCode. Update the serial by increasing it by 1. The serial will need to be higher than the current state file serial before you push it up (please keep this in mind in the event that you have a very old backup and there have been changes since you took a backup)
{
"version": 4,
"terraform_version": "1.11.0",
"serial": 12, <--- [Serial needs to be increased before pushing]
"lineage": "cdce38ed-6720-ea86-1568-5cee9efc78fd",
...
}
Once you have increased the serial, run the following command:
terraform state push backup.tfstate
This will push the backup state file back to the remote backend.
> Azure Portal
Note: If Blob versioning is enabled, that is the recommended option rather than the following manual steps!
Backup State
Option 1: (blob versioning)
Use blob versioning, you only need to restore as all write actions are version controlled.
Option 2: (snapshots)
Go to the storage account
Browse to the blob container and find the state file.
Click on Snapshots
Click Create snapshot
Option 3: (manual)
Go to the storage account
Browse to the blob container and find the state file.
Use Download to save a backup locally.
To restore, use Upload to replace the existing state file.
Restore State
Using blob versioning:
Go to the storage account
Browse to the blob container and find the state file.
Click on Versions
Locate the Version Id by Modified date that you want to restore
Click the 3 dots on the right hand side of the Version
Click Make current version
Using Snapshots:
Go to the storage account
Browse to the blob container and find the state file.
Click on Snapshots
Locate the Name by Modified date that you want to restore
Click the 3 dots on the right hand side of the Version
Click Promote
2. Import Resources
When a resource already exists in Azure but is missing from Terraform state, use terraform import to bring it under Terraforms control.
You will need to have the following ready before importing:
Terraform code already written for the resource you want to import
Know what the target resource reference will be in state
The Resource ID of the resource you want to import.
You can generally get the Resource ID from the Azure portal under the properties configuration blade.
Navigate to the Resource.
Open the Properties blade.
Copy the Resource ID and use it in the terraform import command.
#> Terraform Code
Import blocks were released in Terraform v1.5.0 and later. The feature allows you to import resources using Terraform code, now why would you want to do this?
The import will be executed within the code, this means that the import will run from the build agent (or client) that has permissions and network connectivity to manage and deploy resources to Azure. This is the recommended way if you have any network restrictions to execute terraform state commands locally.
Add the following to import.tf (or in any other Terraform configuration file)
import {
to = module.nsg.azurerm_network_security_group.this
id = "/subscriptions/<subscription_id>/resourceGroups/tf-resources/providers/Microsoft.Network/networkSecurityGroup/nsg-prod-1"
}
Run terraform apply once it has been applied once, it will not run again but its best to remove the code once the apply has run!
3.Move Resources
When refactoring Terraform code, you may need to move resources to avoid configuration changes or destroys. Use terraform state mv to update the state.
A simple example of this is to move a native resource into a module (technically you could remove it from state and then import it but a move would be a single command).
# Before
resource "azurerm_network_security_group" "old" {
...
}
# After
module "nsg3" {
source = "Azure/avm-res-network-networksecuritygroup/azurerm"
...
}
# Terraform CLI
Move in State
terraform state mv \
azurerm_network_security_group.old \
module.nsg3.azurerm_network_security_group.this
#> Terraform Code
Moved blocks were released in Terraform v1.3.x and later. This is the recommended way if you have any network restrictions to execute terraform state commands locally.
Add the following to moved.tf (or in any other Terraform configuration file)
moved {
from = azurerm_network_security_group.old
to = module.nsg3.azurerm_network_security_group.this
}
Run terraform apply once it has been applied once, it will not run again but its best to remove the code once the apply has run!
4. Remove Resources
You want to manually manage a VM outside of Terraform. To manually remove a resource from Terraform state without deleting it in Azure, use terraform state rm.
# Terraform CLI
Remove from State
terraform state rm \
azurerm_linux_virtual_machine.vm
This removes the resource from Terraform state while leaving it in Azure.
Note: There appears to be a limitation at the time of writing that you cannot remove instances of a module, you can only remove the entire module. For example you can only removemodule.vm.azurerum_virtual_machineand notmodule.vm.azurerum_virtual_machine.myfavoritevm. Theterraform state rmcommand is the recommendation option if this does not meet your requirements!
Add the following to removed.tf (or in any other Terraform configuration file)
Note: You need to add thelifecycleparameter to ensure that the resource is not destroyed!
Navigate to the blob container where your state file is stored.
Locate the state file, click Break Lease in the toolbar.
Closing Thoughts
I hope this guide gave you the clarity and confidence to manage your Terraform state like a pro. If you’d like to see these concepts in action, check out the accompanying video above where I walk through real-world examples step by step.
Thanks for reading, and I hope this helped simplify one of the most critical parts of Terraform workflows!
I break down a real-world roadmap to becoming an Azure Cloud Engineer in 2025 - including practical skills, hands-on projects, what tools to learn, and how to actually stand out in a competitive market.