An engineer commits .terraform.lock.hcl and assumes it also pins the registry module that the configuration calls with version = "~> 4.1". Weeks later, a teammate's fresh init installs a newer 4.x module release. Why did this happen, and what pins the module?
Select an answer to reveal the explanation.
Short Explanation
The lock file is a provider-only guest list. Modules aren't on it, so Terraform picks the newest module that fits your constraint every time it installs fresh. If you want the same module every time, write the exact version in the module block.
Full Explanation
The dependency lock file records the provider versions Terraform selected and their checksums, so later runs reuse exactly those provider releases. HashiCorp documents that at present it tracks only provider dependencies: Terraform does not remember version selections for remote modules and always selects the newest available module version that meets the configured constraint. With ~> 4.1, any later 4.x release qualifies, so a fresh init picks it up regardless of the committed lock file. The documented answer is an exact version constraint in the module block, such as version = "4.1.3", changed deliberately when an upgrade is wanted. The -lockfile=readonly mode stops init from modifying the lock file but still only concerns providers; it adds no module tracking. The provider-only behaviour does not depend on whether the module comes from the public or a private registry. The .terraform directory is a local working cache, not a supported pinning mechanism, and is normally excluded from version control. Exam caveat: module pins and the provider lock file are complementary; a reproducible build needs both. Operational check: delete the local .terraform directory, run terraform init, and confirm the module installation output shows the exact pinned version.