Every Terraform project has external dependencies on code that does not exist within the project itself. These external dependencies rely on Terraform Providers and Modules that may exist outside the code base of the Terraform project. Terraform 0.14 and later uses the Dependency Lock File track its decision from one run to another on determining which dependencies are potentially compatible with the current configuration to select the appropriate dependency versions for use.

If you’ve been using Terraform, then you’ve undoubtedly noticed a file named .terraform.lock.hcl get created when you run the terraform init command. This file is the Terraform Lock File. Let’s dig into what this file is for!

Note: The dependency lock file (.terraform.lock.hcl) is a feature that relates to the use of Terraform 0.14 and later, as tracking dependency selections was added in version 0.14. Older versions did not track the dependency selections.

There are two dependency types that Terraform must determine version compatibility for:

  • Terraform Providers – These are the plugins that extend Terraform with support for working with external systems, such as the azurerm provider for managing Microsoft Azure Resources.
  • Terraform Modules – These are reusable groups of Terraform code that can be consumed by multiple Terraform projects.


Determining External Dependency Version Compatibility

When Terraform runs it must determine which versions of dependencies are potentially compatible with the Terraform project code. Each of the dependency types (Providers and Modules) can be versioned and published separately from the Terraform project code that depends on them.

Within the Terraform project, version constraints can be configured for the Terraform project itself to determine which dependency versions are potentially compatible. The version constraints enable a range of acceptable versions of a dependency to be specified within the Terraform project code.

One Terraform determines and selects a specific compatible dependency version, then it stores this decision in the dependency lock file. Storing the decision in the dependency lock file enabled Terraform to use the same decision again in the future without being required to determine it again.

Currently, the Terraform only remembers the Terraform Provider dependency version chosen within the configuration lock file (.terraform.lock.hcl). The version decision for remote Terraform Modules are not remembered via the dependency lock file at this time. As a result, when Terraform is determining the compatible version of modules, it will always select the newest available module version that matches the specified module version constraint.


Terraform Lock File

The Terraform Lock File is always named .terraform.lock.hcl and is located at the current working directory where Terraform is run. This is because the lock file is created to track the compatible dependency versions for the entire Terraform Project, rather than having separate lock files for each individual module in the project. This working directory is also the “root” directory of the Terraform Project itself.

The Terraform Lock File is named .terraform.lock.hcl with the .terraform prefix in it that matches the name of the .terraform directory. The .terraform directory is a hidden directory which is used by Terraform to cache provider plugins and remove modules dependencies referenced by the Terraform project code.

When terraform init command is run, it will automatically create the Terraform Lock File if it doesn’t exist. If the file already exists, then Terraform will update it with the latest dependency versions selected. It is recommended that the lock file be included in version control repositories with the rest of the Terraform (.tf) files for the project.

One of the steps performed by the terraform init command when it’s initializing the Terraform project is to install all of the Terraform Providers needed for the Terraform project code. It takes into account the defined version constraints and the version selection stored in the dependency lock file. If no version is stored in the lock file, then Terraform will select the newest available version that matches the version constraint defined, then update the lock file with this version selection.

When terraform init does update the Dependency Lock File, it will output to the console that these changes were made. The following is what that output looks like:

Terraform has made some changes to the provider dependency selections recorded
in the .terraform.lock.hcl file. Review those changes and commit them to your
version control system if they represent changes you intended to make.

The syntax of the dependency lock file is not Terraform code, but it is the same low-level syntax of HashiCorp Configuration Language (HCL). Therefore the file has the .hcl file extension for HCL rather than the file extension of .tf for Terraform.


Terraform Dependency Version Upgrade

When the Dependency Lock File contains previously selected dependency versions for Provider plugins or modules, then Terraform will always use the versions recorded in the lock file. Re-running the terraform init command will only go through the process of determining the compatible versions of dependencies for any new dependencies added to the project since the previous run.

If you check-in the Dependency Lock File (.terraform.lock.hcl) into source control, this will cause the selected dependency versions to be used from the file.

If you need to force the selected dependency versions to be updated, the -upgrade attribute flag can be added to the terraform init command, as in the following command:

terraform init -upgrade

This -upgrade option will tell Terraform to redetermine the dependency versions again, just like before. This will have the result in Terraform upgrading the project to the latest version of the dependencies. The version constraints will still be factored in when determining the latest compatible version of dependencies, just like when the Dependency Lock File was first created.

Happy Terraforming!

Microsoft MVP

Chris Pietschmann is a Microsoft MVP (Azure & IoT) and HashiCorp Ambassador (2021) with 20+ years of experience designing and building Cloud & Enterprise systems. He has worked with companies of all sizes from startups to Fortune 100. He is also a Microsoft Certified Azure Solutions Architect and developer, a Microsoft Certified Trainer (MCT), and Cloud Advocate. He has a passion for technology and sharing what he learns with others to help enable them to learn faster and be more productive.