How to use terraform depends_on meta argument?

The "depends_on" meta argument in Terraform is used to specify dependencies between resources within a Terraform configuration.

This allows Terraform to properly order the creation, modification, and destruction of resources, ensuring that dependent resources are created or modified only after the resources they depend on have been created or modified.

For example -

Let's say you have a Terraform configuration that creates an Amazon S3 bucket and an Amazon EC2 Instance.

The Amazon EC2 Instance depends on the Amazon S3 bucket, so it needs to be created the bucket before creating the EC2 instance. To specify this dependency, you would use the "depends_on" argument in the object resource block of EC2 Instance, like this:

 1# main.tf 
 2
 3#Step 1 - Create S3 Bucket first
 4resource "aws_s3_bucket" "example_bucket" {
 5  bucket = "example-bucket"
 6}
 7
 8#Step 2 - Create EC2 instance after S3 Bucket
 9resource "aws_instance" "example_instance" {
10  ami           = "ami-0c94855ba95c71c99"
11  instance_type = "t2.micro"
12
13  # Define the dependency on S3 Bucket before creating EC2
14  depends_on = [aws_s3_bucket.example_bucket]
15}

Terraform depends_on meta argument between AWS S3 bucket and EC2 Instance

static

Here is how the above example works -

  1. In the above example, the "aws_instance" resource block contains a "depends_on" argument that references the "aws_s3_bucket" resource block. This tells Terraform that the instance resource depends on the bucket resource, so it should be created or modified only after the bucket resource has been created or modified.

  2. It's important to note that the depends_on argument only affects the order in which resources are created or modified. It does not affect the actual order of destruction. So when you are going to destroy the resources, it will not wait for the dependent resources to be destroyed.

Table of Content

  1. How to specify multiple resources in the "depends_on" meta argument?
  2. How to add module to depends_on meta argument in Terraform?
  3. 5 important things to consider while using depends_on meta argument in terraform?
  4. Why you should use depends_on meta argument as a last resort?
  5. Alternative ways to avoid depends_on meta argument in Terraform?
  6. Conclusion

How to specify multiple resources in the "depends_on" meta argument?

In Terraform, you can specify multiple resources in the "depends_on" meta argument by providing a list of resource references. You must follow the following two conditions -

  1. Each resource reference should be enclosed in square brackets
  2. The list of references should be separated by commas.
1resource "aws_instance" "example_instance" {
2  .....
3  .....
4  depends_on = [aws_s3_bucket.example_bucket, aws_db_instance.example_db]
5  .....
6}

For example, let's say you have a Terraform configuration that creates -

  1. Amazon EC2 instance
  2. Amazon S3 bucket
  3. Amazon RDS database

Dependency Graph

EC2 instance --- Depends On ---> S3 bucket, RDS database

You want the EC2 instance to depend on both the S3 bucket and the RDS database, so you would use the "depends_on" argument in the EC2 resource block like this -

 1#main.tf 
 2
 3# Step 1 - Create an S3 Bucket
 4resource "aws_s3_bucket" "example_bucket" {
 5  bucket = "example-bucket"
 6}
 7
 8# Step 2 - Create an AWS DB Instance
 9resource "aws_db_instance" "example_db" {
10  engine = "mysql"
11  instance_class = "db.t2.micro"
12}
13
14# Step 3 - Create an EC2 Instance with dependency on S3 Bucket, DB Instance
15resource "aws_instance" "example_instance" {
16  ami           = "ami-0c94855ba95c71c99"
17  instance_type = "t2.micro"
18
19  depends_on = [aws_s3_bucket.example_bucket, aws_db_instance.example_db]
20}
21 

In the above example, Terraform tells that the instance resource depends on both the S3 bucket and the RDS database, so it should be created or modified only after both resources have been created or modified.

It's important to note that the order of resource references in the "depends_on" argument does not matter. Terraform will automatically determine the correct order in which to create or modify the resources based on the dependencies specified.


How to add module to depends_on meta argument in Terraform?

In Terraform, when you want to use a module with the "depends_on" meta argument, you can include the module in the "depends_on" argument just like any other resource. You will need to reference the module by its name and the resource defined inside the module that you want to depend on.

Here is an example of how you can use a module with the "depends_on" meta argument:

 1#main.tf
 2
 3#Step 1 : Module for creating S3 Bucket
 4module "s3_bucket" {
 5  source = "./modules/s3-bucket"
 6  bucket_name = "example-bucket"
 7}
 8
 9#Step 2 : Create EC2 Instance with dependency on s3_bucket module 
10resource "aws_instance" "example_instance" {
11  ami           = "ami-0c94855ba95c71c99"
12  instance_type = "t2.micro"
13  
14  #adding module to depends_on block of ec2 instance
15  depends_on = [module.s3_bucket.s3_bucket_resource]
16}
17 

When you want to reference resources inside a module, you will need to use the module's name and the resource name separated by a dot.


5 important things to consider while using depends_on meta argument in terraform?

  1. The order- The order of resource references in the "depends_on" argument does not matter: Terraform will automatically determine the correct order in which to create or modify the resources based on the dependencies specified.

  2. Order of Destruction- The "depends_on" argument only affects the order in which resources are created or modified. It does not affect the actual order of destruction, so when you are going to destroy the resources, it will not wait for the dependent resources to be destroyed.

  3. Circular dependencies- It is important to be aware of circular dependencies, that is when two or more resources depend on each other. This can cause Terraform to fail with an error. It's important to check your dependencies to ensure that there are no circular dependencies.

  4. Dependencies between resources and modules- Be mindful of the dependencies between resources and modules. When you create a resource that depends on another resource in a module, it is important to make sure that the module is properly configured with the correct dependencies.

  5. Test the order of resource creation- It is important to test your Terraform configurations after making changes to the "depends_on" argument to ensure that resources are being created and modified in the correct order. Using terraform plan will show you a preview of what will happen when you run the terraform apply command, it will also show you the dependencies order.


Why you should use depends_on meta argument as a last resort?

depends_on meta argument should be used as a last resort in Terraform

Why?

Here are the reasons why -

  1. It can make your Terraform configurations more complex and harder to understand. The "depends_on" argument is used to specify explicit dependencies between resources, and it can be used to force a specific order for the creation or modification of resources.
  2. Using the depends_on meta argument can also cause issues if not used correctly. For example, if you use depends_on to specify a dependency between two resources that don't actually have a dependency, it could cause an error and can lead to a resource not being created or modified when it should be.

Alternative ways to avoid depends_on meta argument in Terraform?

  1. Using Data Sources: Data Sources allow you to retrieve and use existing resources within your Terraform configuration. By using Data Sources, you can reference existing resources and eliminate the need to use the "depends_on" argument.

Here is an example of the data source in which S3 Bucket is already being created and referenced from aws_s3_bucket_acl resource -

1
2data "aws_s3_bucket" "example_bucket" {
3  bucket = "example-bucket"
4}
5
6resource "aws_s3_bucket_acl" "example" {
7  bucket = aws_s3_bucket.example_bucket.id
8  acl    = "private"
9}
  1. Using Terraform's Count Meta argument: The count meta argument allows you to create multiple resources of the same type with a single resource block. You can use the count meta argument to create resources in a specific order, eliminating the need for the "depends_on" argument.

  2. Using Terraform Provisioners: Provisioners allow you to run scripts or other actions on resources after they have been created. By using provisioners, you can run scripts or other actions that create or configure other resources, eliminating the need for the "depends_on" argument.

In the following example, you can pass in your custom script inside the script.sh and it will execute in that order -

 1resource "aws_instance" "web" {
 2  # ...
 3
 4  provisioner "file" {
 5    source      = "script.sh"
 6    destination = "/tmp/script.sh"
 7  }
 8
 9  provisioner "remote-exec" {
10    inline = [
11      "chmod +x /tmp/script.sh",
12      "/tmp/script.sh args",
13    ]
14  }
15}
16 
  1. Using Terraform Modules: Modules allow you to group resources and manage them as a single unit. By using modules, you can logically organize your resources and eliminate the need to use the "depends_on" argument.

Conclusion

In conclusion, the "depends_on" meta argument in Terraform is a useful tool for specifying dependencies between resources, ensuring that dependent resources are created or modified only after the resources they depend on have been created or modified. This allows Terraform to properly order the creation, modification, and destruction of resources, ensuring that resources are created or modified in the correct order.

Posts in this Series