[Webinar] Policy-as-Code for Secure, Resilient Infrastructure

➡️ Register Now

Terraform

Terraform Refresh Command – Example Usage

Terraform refresh command

Subscribe to our Newsletter

Mission Infrastructure newsletter is a monthly digest of the latest posts from our blog, curated to give you the insights you need to advance your infrastructure game.

In this article, we will explore the terraform refresh command — what it is, how to use it, and the risks of running it.

We will cover:

  1. What is the terraform refresh command?
  2. How to use the terraform refresh command
  3. What to use instead of terrafrom refresh?

Warning: As of Terraform version 0.15.4 and later terraform refresh command is deprecated because its default behavior is unsafe if you have misconfigured credentials for any of your providers.

What is the Terraform refresh command?

The terraform refresh command is used to reconcile the state file with the actual infrastructure. It updates Terraform’s state to reflect the current real-world state of managed resources.

terraform refresh [options]

With options:

  • -var 'key=value': Sets a variable directly from the command line.
  • -var-file=FILE: Loads variables from a file.
  • -lock=true/false: Enables or disables state locking (enabled by default).
  • -lock-timeout=TIMEOUT: Specifies a duration to wait for the state lock.

By running terraform refresh after making manual changes to your infrastructure resources, you ensure that your Terraform state file is up-to-date and reflects the current state of your infrastructure resources.

terraform refresh will not alter any of your real infrastructure but will alter the Terraform state file. It is designed to reconcile any differences from the drift between your infrastructure and the information contained in the state file. It will take into account only objects already in the state file. Any objects outside the state will not be considered and must be imported into the state to be managed by Terraform.

Because the command is included in plan and apply, it typically does not need to be run separately. In fact, Hashicorp recommends you do not use refresh, except for backward compatibility reasons, for use with Terraform versions prior to v0.15.4.

 

When you create a terraform plan or run terraform apply, Terraform automatically refreshes the state of existing objects (this is the default behavior).

How to use the Terraform refresh command

Here are some examples of how terraform refresh works:

Example 1: Using terraform refresh with AWS S3

Start by writing a Terraform configuration to create an S3 bucket:

resource "aws_s3_bucket" "example" {
  bucket = "example-bucket-1234"
  acl    = "private"
}

Run the terraform init and terraform apply to initialize and apply the configuration. This creates an S3 bucket named example-bucket-1234 with the ACL (Access Control List) set to private

Go to the AWS Management Console and modify the S3 bucket settings:

  • Change the ACL from private to public-read.
  • Add a bucket policy to allow public access to the bucket.

Now, run the terraform refresh command. What happens:

  • Terraform queries the current state of the S3 bucket from AWS.
  • The local Terraform state file is updated to reflect the manual changes:
    • The ACL is now public-read.
    • The bucket policy is updated with the newly added policy.

Run terraform plan to review the differences. Based on the terraform plan output, you have two options.

Revert to the desired state

Update the configuration (main.tf) to match the original state:

resource "aws_s3_bucket" "example" {
  bucket = "example-bucket-1234"
  acl    = "private"
}

Apply the configuration to reset the changes.

Accept the changes

Update the Terraform configuration to match the new state:

resource "aws_s3_bucket" "example" {
  bucket = "example-bucket-1234"
  acl    = "public-read"
}

If the bucket policy is required, add it to the configuration as well:

resource "aws_s3_bucket_policy" "example" {
  bucket = aws_s3_bucket.example.id
  policy = <<EOT
  {
    "Version": "2012-10-17",
    "Statement": [
      {
        "Effect": "Allow",
        "Principal": "*",
        "Action": "s3:GetObject",
        "Resource": "arn:aws:s3:::example-bucket-1234/*"
      }
    ]
  }
  EOT
}

Apply the updated configuration.

Example 2: Using terraform refresh with Azure VNET

Let’s use Terraform to create a virtual network (VNET) with subnets:

resource "azurerm_virtual_network" "example" {
  name                = "example-vnet"
  address_space       = ["10.0.0.0/16"]
  location            = "East US"
  resource_group_name = "example-resources"
}

resource "azurerm_subnet" "example" {
  name                 = "example-subnet"
  address_prefix       = "10.0.1.0/24"
  virtual_network_name = azurerm_virtual_network.example.name
  resource_group_name  = "example-resources"
}

Run terraform init and terraform apply to deploy the VNET and subnet, and our local state file will match the actual state of the deployed infrastructure.

Now, modify the VNET or subnet directly in the Azure portal (or any other cloud provider portal). For example, change the subnet address space from 10.0.1.0/24 to 10.0.2.0/24.

Run the terraform refresh command to query the current state of our resources in Azure (or the respective backend) and update the local Terraform state file to reflect the manual change.

After the refresh, run terraform plan.

Terraform will now detect the difference between the desired state (defined in your main.tf) and the updated state (from the terraform refresh command). It will show an execution plan to revert or adapt the configuration to match the desired state.

What to use instead of Terrafrom refresh?

Although terraform refresh command can be a useful diagnostic tool, here are some concerns associated with its usage:

  • terraform refresh updates the Terraform state file with the current real-world infrastructure state. If resources have been changed outside Terraform (e.g., through manual updates), this could result in unanticipated differences. These changes may later cause Terraform to create, modify, or destroy resources unexpectedly during an apply.
  • It queries every resource defined in the Terraform configuration, which can be time-consuming for large infrastructures. Additionally, if there are many or complex providers, the refresh operation could lead to delays or timeouts, affecting workflow efficiency.
  • Frequent or interrupted refresh operations can increase the risk of inconsistencies or corruption in the state file, particularly if there are issues like network interruptions or bugs in the provider APIs. This could lead to errors in subsequent Terraform operations.

The terraform refresh command was deprecated in Terraform 1.6. You can achieve the same functionality using the --refresh-only option, which was introduced to the plan and apply commands for Terraform versions v0.15.4 and above. Now terraform refresh command is essentially an alias to the terraform apply -refresh-only -auto-approve 

Excluding the auto-approve option will prompt you for confirmation before the refresh is performed.

Example: How to use terraform apply -refresh-only command

Assume you have a Terraform configuration managing an AWS S3 bucket. The bucket was modified manually (e.g., enabling versioning) outside Terraform, and you want to update the state to reflect this change.

provider "aws" {
  region = "us-east-1"
}

resource "aws_s3_bucket" "example" {
  bucket = "my-example-bucket"
  acl    = "private"
}

Initialize Terraform (if not already initialized). Before running the --refresh-only command, you can preview changes with:

terraform plan -refresh-only

Output indicates the Terraform state is missing the versioning configuration enabled on the S3 bucket:

Terraform used the selected providers to generate the following execution plan. Any actions below are proposed updates to the state and not your infrastructure.

aws_s3_bucket.example: Refreshing state... [id=my-example-bucket]

~ resource "aws_s3_bucket" "example" {
    id            = "my-example-bucket"
    acl           = "private"
  + versioning {
        enabled = true
    }
}

Plan: 0 to add, 0 to change, 0 to destroy.

Now, run terraform apply -refresh-only.

Output:

Terraform used the selected providers to generate the following execution plan. Any actions below are proposed updates to the state and not your infrastructure.

aws_s3_bucket.example: Refreshing state... [id=my-example-bucket]

~ resource "aws_s3_bucket" "example" {
    id            = "my-example-bucket"
    acl           = "private"
  + versioning {
        enabled = true
    }
}

Do you want to perform these actions in the state? Only 'yes' will be accepted to approve.

Enter a value: yes

aws_s3_bucket.example: Modifications to state completed after 0s

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Note: New versions of Terraform are placed under the BUSL license, but everything created before version 1.5.x stays open-source. OpenTofu is an open-source version of Terraform that expands on Terraform’s existing concepts and offerings. It is a viable alternative to HashiCorp’s Terraform, being forked from Terraform version 1.5.6.

Key points

By running terraform refresh after making manual changes to your infrastructure resources, you ensure that your Terraform state file is up-to-date and reflects the current state of your infrastructure resources. This helps to prevent any conflicts or inconsistencies that might occur when Terraform is used to manage the same resources as other tools or manual changes.

We encourage you to explore how Spacelift makes it easy to work with Terraform. If you need help managing your Terraform infrastructure, building more complex workflows based on Terraform, and managing AWS credentials per run instead of using a static pair on your local machine, Spacelift is a fantastic tool. It supports Git workflows, policy as code, programmatic configuration, context sharing, drift detection, and many more great features right out of the box. 

If you want to learn more about Spacelift, create a free account today or book a demo with one of our engineers.

Terraform management made easy

Spacelift effectively manages Terraform state, more complex workflows, supports policy as code, programmatic configuration, context sharing, drift detection, resource visualization and includes many more features.

Learn more

The Practitioner’s Guide to Scaling Infrastructure as Code

Transform your IaC management to scale

securely, efficiently, and productively

into the future.

ebook global banner
Share your data and download the guide