How to use Terraform refresh-only to prevent state drift and ensure accurate resource management

Learn how to use Terraform's -refresh-only flag to handle state drift, update state files, and prevent unintended changes in your resources.

How to use Terraform refresh-only to prevent state drift and ensure accurate resource management
How to use Terraform refresh-only to prevent state drift and ensure accurate resource management

Terraform relies on a state file to manage the infrastructure it manages. This state file acts as a source of truth, mapping real-world resources to the configurations defined in Terraform.  By maintaining this state, Terraform can determine what changes need to be applied without recreating resources unnecessarily. 

However, there are times when infrastructure isn’t always modified through Terraform.  Changes can be made directly in the infrastructure interfaces, through PowerShell, CLI, etc and this can be what is called state drift. 

State drift occurs when the actual infrastructure differs from what Terraform expects. This can lead to unexpected behaviours when new changes are applied via Terraform. 

To address this, Terraform provides a way to refresh its state by checking the current status of resources and updating the state file accordingly. 

In this blog post, we will explore how Terraform handles state refresh, including the -refresh-only flag, and the key considerations when updating your Terraform state file.

What is Terraform refresh-only?

If your Terraform state drifts because changes are made outside of your Terraform configuration, it’s important to make sure you refresh your state file to check the status of resources and update it accordingly so you can move forward with future changes. 

Terraform can refresh your state file; this was previously done with the terraform refresh command. However, as of Terraform 0.15.4, this command has been deprecated due to concerns about unintended state modifications and lack of user control over changes. 

Instead, Terraform has introduced the command terraform plan -refresh-only or terraform apply -refresh-only.

With this approach, you can run the terraform plan -refresh-only you can see the plan showing exactly what Terraform detects as different in the infrastructure compared to its current state. You can review these differences before deciding whether to apply them.

In contrast, the old terraform refresh command would immediately update the state file without showing you the changes first, potentially leading to unexpected updates that were difficult to track.

Terraform follows a plan-and-apply model to minimise surprises. The -refresh-only flag fits into this model by ensuring that state updates are treated like a change, requiring user approval just like any infrastructure modification.

This structured approach is particularly useful in team environments or CI/CD pipelines, where unintended state changes can lead to confusion or conflicts.

How to use Terraform refresh-only

Before running any commands, ensure that Terraform is initialised and has access to the state file by running the command: terraform init

Then run the following command to compare the current infrastructure with the state file by running:Terraform plan -refresh-only

This command checks for differences between the expected configuration and the actual deployed resources. You can see in the example screenshot below when I run the command it’s compared what the settings should be against what I have within my live Azure environment and highlights some changes. 

To update the Terraform state file without modifying any resources, run:

Terraform apply -refresh-only

This refreshes the state file to reflect the actual environment, ensuring that future Terraform changes are based on the correct resource configurations. This is particularly useful before making further updates to your resources, as it prevents unintended modifications due to outdated state data.

Best practices for using Terraform refresh-only 

Here are some best practices that I have started incorporating into my Terraform workflow:

  • Run terraform plan -refresh-only before every apply, this helps to flag up any issues with drift and prepare me to update my state file if needed before making any resource modifications. 
  • Review changes before applying, if any changes are flagging up I make sure I review the changes before updating my state to understand why the changes have occurred. 

Conclusion

The -refresh-only flag is an important one that you should be aware of to ensure your Terraform state files are kept up to date and help to prevent any unintended changes to your resources.