Skip to main content

Terraform Refresh

Terraform refresh updates the state file to match the current real state of your infrastructure — detecting changes made outside of Terraform. In modern Terraform (1.0+), refresh behaviour is built into every plan and apply by default.

What Is Terraform Refresh?

Terraform's state file is a snapshot of your infrastructure at the time of the last apply. But the real world keeps changing — someone modifies a security group in the AWS console, an auto-scaling group replaces an instance, or a manual CLI command changes a tag.

Terraform refresh reads the current real state of every resource in the state file from the cloud provider's API and updates the state file to match what actually exists. It is how Terraform syncs its memory with reality before deciding what changes to make.

In Terraform 1.0 and later, refresh happens automatically at the start of every terraform plan and terraform apply. You rarely need to run it manually.

Bash
+------------------------------------------+
| terraform.tfstate (last apply) |
| security_group.web: |
| ingress port 443: 0.0.0.0/0 |
+------------------------------------------+
|
v (terraform refresh)
+------------------------------------------+
| Read real AWS resource via API |
| security_group.web: |
| ingress port 443: 0.0.0.0/0 |
| ingress port 22: 0.0.0.0/0 <- NEW |
| (someone added this in the console) |
+------------------------------------------+
|
v
+------------------------------------------+
| Updated terraform.tfstate |
| security_group.web: |
| ingress port 443: 0.0.0.0/0 |
| ingress port 22: 0.0.0.0/0 <- added |
| State now reflects reality |
+------------------------------------------+

How Refresh Fits Into Modern Terraform

Bash
# terraform plan already refreshes state automatically
# It reads real infrastructure before calculating the diff
terraform plan
# Refreshing state... aws_instance.web
# Refreshing state... aws_s3_bucket.assets
# Refreshing state... aws_security_group.web
# (then shows the plan)
# Skip refresh if you know nothing changed externally (faster for large configs)
terraform plan -refresh=false
# Refresh state and show what drifted — WITHOUT making any infrastructure changes
terraform apply -refresh-only
# This updates your state file to match reality
# It does NOT modify any real infrastructure
# Useful for acknowledging manual changes you want to keep
# Preview what refresh-only would change before committing
terraform plan -refresh-only

When to Use apply -refresh-only

The terraform apply -refresh-only command is the modern replacement for the old standalone terraform refresh command (which is deprecated). Use it when:

  • Someone made a manual change in the console that you want to keep — refresh-only updates state to accept it without reverting it
  • Your state file is out of sync with reality and you want to resync without making infrastructure changes
  • You are debugging drift and want to see what changed before deciding what to do
Bash
# Scenario: an engineer added a tag manually in the AWS console
# You want to accept this change without reverting it
terraform plan -refresh-only
# ~ aws_instance.web will be updated in state
# ~ tags["TemporaryFix"] = null -> "incident-24-resolved"
# Would update Terraform state to reflect these changes.
# Note: this plan does not change any real infrastructure.
terraform apply -refresh-only
# State updated. No infrastructure was changed.
# The manual tag is now recorded in state.

The Deprecated terraform refresh Command

Bash
# This command still exists but is deprecated in Terraform 1.x
# Do not use it in new workflows
terraform refresh
# Deprecated: use terraform apply -refresh-only instead

Disabling Refresh for Speed

For large configurations with hundreds of resources, the refresh step can take minutes — each resource requires an API call to the cloud provider. If you are confident nothing has changed externally, skip refresh:

Bash
# Skip refresh — plan uses state file as-is without checking real infrastructure
# Only use this when you are certain no external changes have been made
terraform plan -refresh=false
terraform apply -refresh=false

Troubleshooting Refresh

Situation What It Means What to Do
Plan shows unexpected changes after refresh State was out of sync — someone changed a resource externally Review the changes — revert them with apply, or accept them with apply -refresh-only
Refresh is very slow Large number of resources, each requires an API call Use -refresh=false if you trust nothing changed externally
Resource shows as deleted after refresh Resource was manually deleted in the console Remove from state with terraform state rm or recreate with terraform apply
Error: Inconsistent dependency lock file Lock file mismatch Run terraform init -upgrade
Tip

Run terraform plan -refresh-only as a scheduled job (daily or weekly) in CI/CD to detect drift automatically. If the plan shows any changes, alert the team that someone has modified infrastructure outside of Terraform.

Frequently Asked Questions

Do I still need to run terraform refresh manually in modern Terraform?

No — since Terraform 0.15/1.0, refresh behavior runs automatically as part of every `terraform plan` and `terraform apply`, so the standalone `terraform refresh` command is rarely needed directly anymore; it's kept mostly for scripting or debugging scenarios where you want to update state without generating a plan. If you do need the old standalone behavior, `terraform apply -refresh-only` is now the recommended, safer way to do it since it still shows you a reviewable diff before updating state.

What's the risk of running a refresh-only apply carelessly?

Refresh updates Terraform's state to match reality, which means if someone manually changed a resource outside of Terraform (a classic case of 'ClickOps' drift), a refresh will accept that manual change into state as the new source of truth — silently overwriting what your .tf configuration says should be true, rather than flagging it as drift to fix. Always review a refresh-only plan's diff before confirming, since it can mask configuration drift that actually should be corrected, not accepted.