# Correct way to handle provider versions in child modules

**URL:** <https://discuss.hashicorp.com/t/correct-way-to-handle-provider-versions-in-child-modules/35127>\
**Category:** Terraform\
**Created:** [February 2, 2022, 4:48pm UTC](https://discuss.hashicorp.com/t/correct-way-to-handle-provider-versions-in-child-modules/35127 "2022-02-02T16:48:56Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![methylamin](https://sea2.discourse-cdn.com/hashicorp/user_avatar/discuss.hashicorp.com/methylamin/32/16549_2.png) [@methylamin](https://discuss.hashicorp.com/u/methylamin)\
**Post date:** [February 2, 2022, 4:48pm UTC](https://discuss.hashicorp.com/t/correct-way-to-handle-provider-versions-in-child-modules/35127/1 "2022-02-02T16:48:56Z")

</div>

Hi, I am trying to understand how under Terraform v1.0+ the correct provider version should be specified for the child modules. A concrete example is any of the [Terraform AWS modules](https://registry.terraform.io/namespaces/terraform-aws-modules). Here it says in the root module as well as in the child module:

**versions.tf**

```auto
terraform {
  required_version = ">= 0.13.1"

  required_providers {
    aws = {
      source = "hashicorp/aws"
      version = ">= 3.28"
    }
  }
}

```

In comparison [Azure](https://registry.terraform.io/browse/modules?provider=azurerm) only has an almost empty file in the root module level:

**versions.tf**

```auto
terraform {

}

```

Is this the way to go for custom modules? And if should I do the same for the provider block?

---

<div class="post-metadata">

**Author:** ![apparentlymart](https://sea2.discourse-cdn.com/hashicorp/user_avatar/discuss.hashicorp.com/apparentlymart/32/702_2.png) [@apparentlymart](https://discuss.hashicorp.com/u/apparentlymart)\
**Post date:** [February 2, 2022, 5:19pm UTC](https://discuss.hashicorp.com/t/correct-way-to-handle-provider-versions-in-child-modules/35127/2 "2022-02-02T17:19:15Z")

</div>

Hi @methylamin,

As a concession to backward-compatibility with modules written for Terraform v0.12 and earlier, Terraform v0.13 and later (including v1.0+) have a heuristic for automatically inferring provider requirements that aren’t explicitly declared:

For each `resource` block, take its resource type name (the first label, like `aws_instance`) and extract the prefix up to the first `_`. If that prefix doesn’t match one of the local names declared in the module’s `required_providers` block (or if the module doesn’t have one) then Terraform will infer one automatically, by placing the extracted prefix after `hashicorp/` to create a `source` address, and by leaving `version` unset so as to take the latest available version of that provider.

In your second example here then, if there were a resource block elsewhere in the module with a type like `azurerm_resource_group`, Terraform would automatically infer a provider requirement declaration like this:

```auto
terraform {
  required_providers {
    azurerm = {
      source = "hashicorp/azurerm"
    }
  }
}

```

If you are writing your own module and don’t have any need to support Terraform v0.12 and earlier then I would recommend writing out an explicit `required_providers` block like the one you showed with the `hashicorp/aws` provider. A good required providers block for a shared module should declare both the source address (`hashicorp/aws` in that case) and a minimum provider version that supports all of the features and behaviors the module is relying on.

Various modules in Terraform Registry were originally written to support older versions of Terraform and so often use some different approaches to remain compatible with those older versions. I assume that’s true for some of the modules you found by searching for “azurerm” in the public registry. Terraform v0.12 only partially understands this `required_providers` syntax, and earlier versions don’t understand it at all, so omitting it can be a reasonable strategy for a module that needs to support a broad set of Terraform language versions and which only relies on relatively-recent provider features such that it’s unlikely that a new user would select an incompatible old version of the provider.
