Skip to main content
Terraform detects drift between the configuration in your code, the saved state, and the real-world resources in Azure by performing a state refresh. Understanding this refresh process explains why terraform plan or terraform apply can change even when you didn’t edit any files.
Terraform performs a state refresh automatically during plan and apply. The provider queries Azure for current resource attributes, compares those live values with your configuration and the saved state, and produces a plan that reconciles any differences. This is how Terraform detects drift and keeps your infrastructure consistent.
What happens during a refresh
  • Terraform calls the provider (here: AzureRM) to fetch the current resource attributes.
  • It compares those live attributes against:
    • the values in your Terraform configuration, and
    • the values stored in terraform.tfstate.
  • Any mismatches produce a plan to reconcile differences (for example, an in-place update).
Example scenario
  • You create an Azure Storage Account. By default the storage account setting public_network_access_enabled is true.
  • Later you change your Terraform configuration to set public_network_access_enabled = false.
Desired configuration (HCL):
What Terraform does when you run terraform plan
  • Terraform refreshes the resource state from Azure.
  • It discovers the actual value (for example, true) and compares it to the configured value (false).
  • Terraform generates a plan showing an in-place update from truefalse.
Example plan output (trimmed):
This demonstrates how Terraform detects and corrects drift: the state refresh ensures plans reflect live infrastructure and catch external changes. Skipping refresh with -refresh=false You can skip the state refresh by passing -refresh=false to terraform plan or terraform apply. When you do, Terraform trusts the state file and will not query Azure for current resource attributes. Use cases:
  • Speeding up operations in isolated test environments where you control all changes.
  • CI pipelines where you have confidence no out-of-band changes occur.
Risks and important behaviors:
  • If the state file is outdated, skipping refresh can cause Terraform to apply unnecessary changes or to miss real drift.
  • If the state and your configuration already match, skipping refresh produces a no-op even if Azure has diverged.
Table: useful commands and their effects
Skipping refresh with -refresh=false can be dangerous in production: it hides drift and can cause configuration and real infrastructure to silently diverge. Prefer the default refresh behavior for safety and predictable outcomes.
Concrete demo (reproducible in Visual Studio Code) Below is a concise demo you can reproduce to observe state refresh behavior.
  1. Minimal Terraform configuration: provider, resource group, and storage account.
  1. Initialize, plan and apply:
Terraform will create the resource group and the storage account. Protecting the state file After applying, terraform.tfstate contains resource attributes (including sensitive values like storage account keys). Example snippet:
Because the state can contain secrets and sensitive attributes, ensure:
  • State is stored securely (use remote state backends like Azure Storage with proper access controls).
  • Do not commit terraform.tfstate to public repositories.
  1. Change the storage account config to disable public network access:
  1. Run terraform plan (default behavior). Terraform will refresh state, query Azure, detect that the existing setting is true, and plan an in-place update to set it to false:
  1. Example: apply while skipping refresh
Outcomes to expect:
  • If your state still showed true (and Azure is true), skipping refresh will still apply the change and update state.
  • If your state already showed false, but someone manually changed Azure back to true, then --refresh=false will skip detection and do nothing—leaving Azure and state/config out of sync. This is the risky scenario.
Observe the Azure portal After applying a change, confirm it in the portal. For example, open the storage account in the Azure portal, go to Security and Networking → Networking, and verify the public network access setting reflects Terraform’s change.
This image shows a Microsoft Azure portal interface for managing a storage account named "ststaterefreshdemo," displaying properties like resource group, location, and security settings. Various features and settings related to the storage account are also shown, including Blob service configurations, security, and networking.
If you manually toggle that setting back to Enabled in the portal and save it, Terraform will detect that drift the next time it refreshes the state and will plan to reconcile it (unless you use -refresh=false).
The image shows a Microsoft Azure settings page for configuring public network access, with options to enable or restrict access for a resource. It features selections for the scope of access, including options for all networks or selected networks.
Summary — Key takeaways
  • Default Terraform behavior is to refresh state before planning or applying; this ensures plans reflect live infrastructure and detect out-of-band changes.
  • -refresh=false can speed up execution but is risky: it relies solely on the state file and can hide drift.
  • In production, prefer the default refresh behavior for safety, accuracy, and predictable outcomes.
Further reading and references

Watch Video