TrademarkTrademark
Features
Documentation

Terraform Resource Dependencies Explained

The power of TF is its ability to have dependencies between resources, and even data sources, learn how to use them.
Brendan ThompsonJanuary 12, 2023
Terraform Resource Dependencies Explained
Key takeaways
  • Terraform dependencies come in two forms: implicit, where a resource references another resource or data source, and explicit, declared with depends_on.
  • Implicit dependencies form automatically when one resource references another's attributes, and Terraform builds them into the resource graph to control creation order.
  • Replacing references with hard-coded values removes implicit dependencies, causing Terraform to create resources at the same time and fail when one depends on another not yet created.
  • The depends_on block lets engineers explicitly declare dependencies between resources or data sources for technical or business reasons.
  • Dependencies ensure resources are created in the correct order, which is a core part of Terraform's power as an infrastructure-as-code tool.

Terraform lets you declare dependencies between resources, and even between data sources. There are two kinds:

  • Implicit - where a resource references another resource/data source
  • Explicit - where an engineer explicitly calls out a dependency between two resources/data sources

Either way, a dependency stops Terraform from creating a resource before the thing it needs already exists. The rest of this post walks through an example of each.

Implicit

The example below creates three resources that depend on each other: a Resource Group, a Virtual Network, and a Subnet. In the code, each one references the others in some way. The Virtual Network references the Resource Group twice, once for its location and once for its name.

Terraform sees this reference and creates a dependency for us in the resource graph between those particular resources.

resource "azurerm_resource_group" "this" {
  name     = "rg-implicit-dependency"
  location = "Australia East"
}
 
resource "azurerm_virtual_network" "this" {
  name                = "vn-implicit-dependency"
  location            = azurerm_resource_group.this.location
  resource_group_name = azurerm_resource_group.this.name
 
  address_space = ["10.0.0.0/24"]
}
 
resource "azurerm_subnet" "this" {
  name                 = "sn-implicit-dependency"
  resource_group_name  = azurerm_resource_group.this.name
  virtual_network_name = azurerm_virtual_network.this.name
 
  address_prefixes = ["10.0.0.0/28"]
}

The below diagram is the output of the terraform graph command piped into https://github.com/pcasteran/terraform-graph-beautifier. Now you can visually see those references between each resource.

Output of the terraform graph

Output of the terraform graph

To prove the point, let's change the code so it uses hard-coded values instead of references. The code now looks like this:

resource "azurerm_resource_group" "this" {
  name     = "rg-implicit-dependency"
  location = "Australia East"
}
 
resource "azurerm_virtual_network" "this" {
  name                = "vn-implicit-dependency"
  location            = "Australia East"
  resource_group_name = "rg-implicit-dependency"
 
  address_space = ["10.0.0.0/24"]
}
 
resource "azurerm_subnet" "this" {
  name                 = "sn-implicit-dependency"
  resource_group_name  = "rg-implicit-dependency"
  virtual_network_name = "vn-implicit-dependency"
 
  address_prefixes = ["10.0.0.0/28"]
}

If we were to run the terraform graph command again we would get a different result entirely! As you can see below we no longer have those dependencies demarcated by arrows in the resource graph.

Resources without dependencies

Resources without dependencies

With this configuration Terraform will try to create all three resources at the same time - this can be limited with the parallelism command line option for apply - which will result in an error!! An example is below which shows that the Virtual Network cannot find the existence of the Resource Group we are referencing.


│ Error: creating/updating Virtual Network: (Name "vn-implicit-dependency" / Resource Group "rg-implicit-dependency"): network.VirtualNetworksClient#CreateOrUpdate: Failure sending request: StatusCode=404 -- Original Error: Code="ResourceGroupNotFound" Message="Resource group 'rg-implicit-dependency' could not be found."

│   with azurerm_virtual_network.this,
│   on main.tf line 10, in resource "azurerm_virtual_network" "this":
│   10: resource "azurerm_virtual_network" "this" {

Explicit

We've seen implicit dependencies in action. Here's how explicit ones work. We'll reuse the example from above, which is currently broken because it has no dependencies in place, and fix it with explicit dependencies.

resource "azurerm_resource_group" "this" {
  name     = "rg-explicit-dependency"
  location = "Australia East"
}
 
resource "azurerm_virtual_network" "this" {
  name                = "vn-explicit-dependency"
  location            = "Australia East"
  resource_group_name = "rg-explicit-dependency"
 
  address_space = ["10.0.0.0/24"]
 
  depends_on = [
    azurerm_resource_group.this
  ]
}
 
resource "azurerm_subnet" "this" {
  name                 = "sn-explicit-dependency"
  resource_group_name  = "rg-explicit-dependency"
  virtual_network_name = "vn-explicit-dependency"
 
  address_prefixes = ["10.0.0.0/28"]
 
  depends_on = [
    azurerm_resource_group.this,
    azurerm_virtual_network.this
  ]
}

Each resource now has a new block called depends_on. It lets us, as engineers, call out explicit dependencies between resources or data sources. Instead of references, the example uses the literal names of the Resource Group and Virtual Network. In a real setup these would more likely be input variables passed in. This also helps when two services have a business dependency rather than a technical one.

The below screenshot shows what our graph will look like when we use the depends_on. (I promise it's not copy paste from above)

Terraform graph showing explicit dependencies using depends_on block

Closing out

We've looked at the two ways to declare dependencies in Terraform code. Implicit dependencies come from referencing one resource or data source inside another. Explicit ones use the depends_on block to tell Terraform about a dependency directly. Both make sure resources are created in the right order, whether the reason is technical or a business constraint. It's one more thing that makes Terraform a capable infrastructure-as-code tool.

About the author
Brendan Thompsonsolutions engineer at Scalr
Brendan Thompson is a solutions engineer at Scalr, specializing in Terraform and cloud infrastructure.