
Terraform lets you declare dependencies between resources, and even between data sources. There are two kinds:
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.
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
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
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" {
│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)

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.
