Terraform Best Practices

Chapter 2 · Practice 1 of 4

Constrain the Terraform version and every provider

From Versions and dependencies

Why it matters

A new major provider version can rename arguments or change defaults, and an unpinned configuration picks it up on the next init. The style guide says to set required_version and to pin every provider in required_providers.

The version constraint docs give different advice for root modules and reusable modules:

WhereConstraintWhy
Root module~>, bounded on both sidesUpgrades become a deliberate change
Reusable moduleA minimum only, such as >=Callers can upgrade without editing your module

The ~> operator allows only the right-most component you wrote to increase. ~> 6.0 allows 6.1 and 6.20 but not 7.0. ~> 6.0.4 allows 6.0.5 but not 6.1.0.

To check, run terraform version in CI and confirm it reports the expected Terraform and provider versions on every run.

Example

HCL
terraform {
  required_version = "~> 1.16"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 6.0"
    }
  }
}