How to Use Terraform `depends_on`
Tags: iac, terraform, devops, azure
Published: 2022-10-27 04:00:00

In this article you will learn why and how to use Terraform's `depends_on` meta-argument.

## Resource Dependencies

Terraform uses resource dependencies to create and destroy resources in the correct order. [Expression references](https://developer.hashicorp.com/terraform/language/expressions/references) create *implicit* dependencies between one resource and another resource. The following shows an implicit dependency created between two Azure resources using an expression reference.

```terraform
resource "azurerm_resource_group" "rg" {
  name     = "rg-example-centralus"
  location = "centralus"
}

resource "azurerm_virtual_network" "vnet" {
  name                = "vnet-example-centralus"
  resource_group_name = azurerm_resource_group.rg.name
}
```

In this example, an implicit dependency is created because the VNet's `resource_group_name` attribute references the name of the resource group. The object with the dependency, the VNet, is referred to as the "object declaring the dependency", and the resource group is referred to as the "dependency object". Terraform completes all actions on the dependency object first, then performs actions on the object declaring the dependency.

## What is Terraform `depends_on`

In the majority of scenarios, Terraform automatically determines dependencies between resources based on expressions within a resource block. There are rare scenarios, however, where Terraform cannot infer dependencies between resources. In these cases, you will need to create an *explicit* dependency. This is the purpose of the `depends_on` meta-argument. `depends_on` allows you to create an explicit dependency between two resources.

Dependencies are not limited to just resources. Dependencies can be created between modules. When the dependency is a module, `depends_on` affects the order in which Terraform processes all the resources and data sources associated with that module. Both implicit and explicit dependencies affect the order in which resources are destroyed as well as created. Explicit dependencies are only necessary when a resource or module relies on another resource's behavior but does not access any of that resource's data in its arguments.

There are some things you should consider when using `depends_on`:

- Always include a comment to explain why using `depends_on` is necessary.

- `depends_on` causes Terraform to create a more conservative plan. The plan may modify more resources than necessary. For example, there may be more values as unknown “(known after apply)”. This is more likely to occur when creating explicit dependencies between modules.

- Adding explicit dependencies can increase the length of time it takes to build your infrastructure because Terraform must wait until the dependency object is created before continuing.

- It is recommended to use expression references to create implicit dependencies whenever possible.

## Use Cases for `depends_on`

Some scenarios that may require the use of an explicit dependency include running a SQL script after a DB is created, deploying containers only after the container registry is created, or you have an application running on a VM instance that expects to use a specific Azure Storage Container. This dependency is not visible to Terraform since the application’s architecture controls it. The following snippet demonstrates an explicit dependency between a VM and a storage container.

``` terraform
resource "azurerm_windows_virtual_machine" "vm" {
  resource_group_name      = "rg-demo"
  name                     = "vm-demo"
  location                 = "centralus"

  size                     = "Standard_F2"
  admin_username           = "adminuser"
  admin_password           = "P@$$w0rd1234!"
  network_interface_ids    = [
    azurerm_network_interface.nic.id,
  ]

  os_disk {
    caching              = "ReadWrite"
    storage_account_type = "Standard_LRS"
  }

  # all other relevant attributes
 
 depends_on = [
    azurerm_storage_account.st
 ]
}

resource "azurerm_storage_account" "st" {
  resource_group_name      = "rg-demo"
  name                     = "stdemo"
  location                 = "centralus"
  account_tier             = "Standard"
  account_replication_type = "LRS"
  # all other relevant attributes
}
```

### Adding Multiple Dependency Objects

Multiple dependencies can be passed to the `depends_on` argument using a comma separated list of resources. Note: adding explicit dependencies can increase the length of time it takes to create your infrastructure because Terraform will wait to create the dependent resource until after the specified resource is created. The following snippet expands on the example from above and adds a second dependency, an Azure SQL Server, to the VM. This example is for illustration purposes and does not represent the best use case for creating an explicit dependency to multiple resources.

```terraform
resource "azurerm_windows_virtual_machine" "vm" {
  # all other relevant attributes
 
 depends_on = [
    azurerm_storage_account.st,
    azurerm_mssql_server.sql
 ]
}

resource "azurerm_mssql_server" "sql" {
  resource_group_name           = "rg-demo"
  name                          = "stdemo"
  location                      = "centralus"
  administrator_login           = "adminuser"
  administrator_login_password  = "P@$$w0rd1234!"
  version                       = "12.0"
  # all other relevant attributes
}
```

### How to use `depends_on` for modules in Terraform

As mentioned above, resources can have explicit dependencies on modules, and vice-versa. This next example uses a module from the Terraform registry to create a VM. The module will be dependent upon the successful creation of the storage account.

```terraform
module "virtual-machine" {
  source = "Azure/network/azurerm"
  resource_group_name           = "rg-demo"
  # all other relevant attributes

  depends_on = [
      azurerm_storage_account.st
  ]  
}

resource "azurerm_storage_account" "st" {
  # all other relevant attributes
}
```

Here's an example of the same two resources with the dependency reversed. In this example the storage account resource is dependent upon the vm module. Note the use of the `module` keyword in the dependency resource.

```terraform
module "virtual-machine" {
  source = "Azure/network/azurerm"
  resource_group_name           = "rg-demo"
  # all other relevant attributes
}

resource "azurerm_storage_account" "st" {
  # all other relevant attributes
  depends_on = [module.virtual-machine]
}
```

Understanding how Terraform uses implicit and explicit dependencies helps you to determine when and how to use the `depends_on` meta-argument. When necessary, `depends_on` instructs Terraform to create and destroy resources in the correct order. Misusing the argument can lead to potentially confusing, poor performing code.