Courseiva
TF-003Chapter 9 of 15Objective 4.2

Resource Dependencies and Lifecycle Management

Resource dependencies and lifecycle management. This is the part of Terraform that makes sure your cloud resources are created, updated, and destroyed in the right order, without breaking anything. For someone studying TF-003, understanding this is crucial because the exam tests your ability to read and write configuration that controls how Terraform handles changes, including automatic dependency resolution and custom lifecycle rules.

12 min read
Intermediate
Updated Jul 23, 2026
Reviewed by Johnson Ajibi· Senior Network & Security Engineer · MSc IT Security

A simple way to picture Resource Dependencies and Lifecycle Management

The Kitchen Renovation Manager Analogy

The kitchen renovation manager is the person who makes sure your new kitchen is built correctly, in the right order, and that it doesn't get damaged during the install. Imagine you are renovating a kitchen from scratch. The manager knows that the plumbing must be installed before the dishwasher can be fitted, and that the wall must be tiled before the cabinets are hung. If the electrician turns up before the plasterer has finished, the wiring might be exposed and unsafe. The manager also has a rule about what happens if a cabinet is damaged during delivery: they will replace it but first ensure the old one is safely removed to avoid cluttering the workspace. This is exactly how resource dependencies and lifecycle management work in Terraform. Terraform is the manager, the cloud resources are the kitchen parts, and the order of installation is the dependency graph. The manager's rule for dealing with damaged goods is the lifecycle customisation. Without the manager, you would have a chaos of tradespeople installing things in the wrong order, causing rework and delays. Terraform's dependency management and lifecycle rules prevent that chaos in your cloud infrastructure.

In this analogy, the renovation manager uses a detailed blueprints to know exactly which part depends on which. They also have a special instruction for fragile items: 'create before destroy' or 'prevent destroy'. For example, if a new granite worktop must be installed before the old one is removed to avoid a gaping hole in the kitchen, the manager uses a 'create before destroy' rule. If a critical support beam must never be removed because the ceiling would collapse, they use a 'prevent destroy' rule. This is a precise translation of Terraform's resource behaviour: you define dependencies implicitly or explicitly, and you set lifecycle rules like 'create_before_destroy' or 'prevent_destroy' to control the order and safety of updates. The renovation manager is the master of this process, and that is exactly what Terraform does for your cloud resources.

How It Actually Works

Let us start with the basics. In Terraform, a 'resource' is a single component of your infrastructure, like a virtual machine (a computer in the cloud), a database, or a network firewall. These resources almost never exist in isolation. For example, you cannot create a virtual machine without first having a 'subnet' (a section of a network) to put it in. You cannot create a subnet without a 'VPC' (a private cloud network). This chain of 'needs' is called a 'dependency'. Terraform automatically figures out which resource depends on which by looking at the configuration you write. If you reference one resource inside another, that creates an 'implicit dependency'. For example, if you write subnet_id = aws_subnet.my_subnet.id, Terraform knows the virtual machine depends on that specific subnet and will create the subnet first.

Sometimes, though, you need to tell Terraform about a dependency that is not obvious from the configuration code. This is called an 'explicit dependency' using the depends_on argument. Imagine you have a database and a backup service that must run after the database is fully ready. Terraform cannot guess that relationship from the code alone, so you add depends_on = [aws_db_instance.my_db] to the backup resource. This is like telling the renovation manager that the tiler must finish before the painter arrives, even though the blueprints don't show a direct link. depends_on is useful but use it sparingly because it can make your configuration harder to maintain.

Now, let us talk about 'resource addressing'. In Terraform, every resource has a unique address that you use to refer to it. This address is written as type.name or type.name[0] for resources created with count or for_each. For example, aws_instance.web or aws_instance.web[0] for the first web server. This address is like a postal address for each resource. When you run terraform plan or terraform apply, you can target a specific resource by its address. Resource addressing also allows you to reference attributes of a resource, like its IP address or name, using syntax like aws_instance.web.private_ip. Understanding addresses is essential for reading Terraform outputs and for debugging.

Lifecycle management is about controlling the what, when, and how of resource changes. Terraform has a 'lifecycle' block that you can use inside a resource definition to customise its behaviour. The three main settings are:

create_before_destroy: When Terraform needs to update a resource, it normally destroys the old one first and then creates the new one. For critical components like a load balancer (which distributes traffic), you want the new one created first so there is no downtime. This setting flips the order.

prevent_destroy: This is a safety lock. If you set it to true, Terraform will refuse to destroy that resource, even if you try to delete it from your configuration. It is like putting a 'do not remove' sign on a load-bearing wall.

ignore_changes: This tells Terraform to ignore specific attributes of a resource when comparing the real world to your configuration. For example, if someone manually adjusts the size of a server, you might want Terraform not to change it back. You list the attributes to ignore, like ignore_changes = [instance_type].

precondition and postcondition: These are advanced checks that run before or after resource operations. They let you validate that data meets certain criteria, like ensuring a database is encrypted before creation. They are like quality control inspectors.

Why does all this exist? Because without it, infrastructure changes would be chaotic. Imagine a company that runs an online shop. If they update the database server without using create_before_destroy, the old database is deleted before the new one is created, causing the shop to go offline for minutes or hours. prevent_destroy protects critical data like a master database that must never be deleted accidentally. ignore_changes helps when other tools or people modify resources outside Terraform, preventing Terraform from fighting with those changes.

The TF-003 exam tests your ability to recognise these concepts. You might be shown a configuration with depends_on and asked what it does. You might be asked what happens when create_before_destroy is set to true. You need to understand the difference between implicit and explicit dependencies, and when to use each. You also need to know that prevent_destroy is defined on a resource, not globally, and that it only prevents destruction via Terraform (not manual deletion in the cloud console).

Flowchart showing how Terraform processes resource dependencies, lifecycle rules, and execution order from user configuration to plan application.

Walk-Through

1

Define Resources with Implicit Dependencies

Write your Terraform configuration with resources that reference each other. For example, an AWS EC2 instance referencing a subnet's ID. Terraform analyses these references to build a dependency graph automatically. This step matters because it ensures resources are created in the correct order without extra code.

2

Add Explicit Dependencies Where Needed

When a dependency cannot be inferred (like a script that runs after a database is created but does not reference it), add the `depends_on` argument to the resource. This tells Terraform to wait for the listed resources before creating the current one. This step prevents order-related errors in complex configurations.

3

Configure Resource Addressing

Use resource addresses like `aws_instance.web` or `aws_instance.web[0]` to reference specific resources or outputs. Addresses are used in outputs, state commands, and targeting. This step is essential for debugging and for writing outputs that share infrastructure details.

4

Apply Lifecycle Rules for Safety

Inside a resource block, add a `lifecycle` block with settings like `create_before_destroy = true` for zero-downtime updates, `prevent_destroy = true` for critical resources, or `ignore_changes` to skip specific attribute changes. This step customises Terraform's behaviour to match your operational needs.

5

Review Plan Output Before Applying

Run `terraform plan` to see the execution order and verify that dependencies and lifecycle rules are working as expected. The plan shows which resources will be created, updated, or destroyed, and in what sequence. This step helps catch mistakes before making changes.

What This Looks Like on the Job

Let us imagine you work as a junior cloud engineer at a company called 'StreamFlix', which runs a video streaming service. StreamFlix is deploying a new feature: a recommendation engine that requires a new database, a server, and a cache (a temporary storage for fast data retrieval). You have written Terraform code to create these resources. Here is what your day might look like.

First, you write a configuration file that defines an AWS RDS database (relational database service) for user data, an EC2 instance (a virtual server) for the recommendation engine, and an ElastiCache cluster (a managed cache service) for session data. You know that the EC2 instance needs the database connection string, so you reference the database resource in the instance configuration. That creates an implicit dependency: Terraform will create the database before the server. You also know the cache must be created after the database because the cache will pull data from the database. You add an explicit depends_on to the cache resource to ensure the order is correct, even though the cache code does not directly reference the database resource.

Now, let us walk through the deployment steps:

Step 1: You run terraform plan. Terraform reads your config and builds a dependency graph. It sees that the database has no dependencies, so it will be created first. The EC2 instance depends on the database, and the cache depends on the database and indirectly on the EC2 instance (because of your explicit depends_on). The plan shows the order: database first, then EC2 instance and cache in parallel (because they don't depend on each other).

Step 2: You run terraform apply. Terraform creates the database. Then it creates the EC2 instance and the ElastiCache cluster. The EC2 instance gets an IP address, and this is outputted via a Terraform output block. You then configure the application to use that IP. Everything works.

Step 3: A week later, a security update is needed for the EC2 instance. You change the AMI (the machine image) in your code. Terraform detects the difference. Because you have not added any lifecycle rules, Terraform will destroy the old instance and create a new one. But for StreamFlix, even a momentary shutdown of the recommendation engine causes buffering for users. So you decide to add create_before_destroy = true to the EC2 instance resource. Now, Terraform will create the new instance first, then switch traffic over, then destroy the old one. No downtime.

Step 4: The database contains critical user data. You never want to accidentally delete it. You add prevent_destroy = true to the database resource. If someone accidentally removes the database from your configuration file, Terraform will refuse to apply the change, keeping the database safe.

Step 5: Later, a developer manually changes the cache cluster's node type from the AWS console. This is outside Terraform. When you run terraform plan, Terraform detects that the configuration says one thing (t2.small) but the real world has something else (t2.medium). Terraform wants to change it back. Instead of causing a conflict, you add ignore_changes = [node_type] to the cache resource, telling Terraform to ignore that attribute. Now, the manual change is accepted, and Terraform will not revert it.

This real-world scenario shows exactly how resource dependencies and lifecycle management keep StreamFlix's streaming service stable and secure. As a beginner, you would start by writing simple configurations, but soon you will need to use these features to manage complex environments. The exam expects you to know these use cases.

How TF-003 Actually Tests This

The TF-003 exam will test your understanding of resource dependencies and lifecycle management in several specific ways. First, expect questions that ask you to identify whether a dependency is implicit or explicit. The exam might present a configuration block and ask, 'Which resource depends on which?' You need to recognise that referencing a resource attribute (like id or arn) creates an implicit dependency. The trap is that sometimes beginners think depends_on is the only way to create dependencies, but the exam will test that implicit dependencies are the primary method.

Second, the exam loves to test the depends_on argument. You may see a question like, 'When would you use depends_on instead of implicit dependencies?' The correct answer is when the dependency is not obvious from the code. For example, if a resource relies on a side effect of another resource, like a database seeding script that must run after the database is created but does not reference the database in its configuration. The trap is that some candidates use depends_on for every dependency, which is unnecessary and verbose. The exam tests that you understand its specific purpose.

Third, lifecycle rules are a hot topic. Expect questions about create_before_destroy and prevent_destroy. A typical question: 'What is the effect of setting create_before_destroy = true on a resource?' Answer: Terraform will create the new version of the resource first, then destroy the old one. Another trap: candidates confuse create_before_destroy with prevent_destroy. Remember, create_before_destroy does not prevent destruction; it only changes the order. prevent_destroy prevents any destruction at all.

Fourth, ignore_changes is tested. You may be asked what happens when ignore_changes is set. The correct answer is that Terraform will not try to modify the specified attributes, even if they differ from the configuration. The trap is thinking that ignore_changes skips the resource entirely it does not; it only ignores changes to specific attributes. The resource is still managed, and other changes are applied.

Fifth, resource addressing appears in questions about outputs and state files. You might be asked, 'What is the address of the first instance created with count = 3?' The answer is resource_type.name[0]. The trap is thinking it is resource_type.name[1] because of human counting vs. zero-based indexing. Resources are addressed starting from 0.

Finally, the exam tests that you know lifecycle blocks are optional and only exist within resource definitions. They are not global settings. Also, note that prevent_destroy and create_before_destroy are only effective if Terraform is managing the resource's lifecycle. If you delete the resource from configuration, prevent_destroy will block the operation. If you use create_before_destroy, Terraform will still destroy the old resource after creating the new one.

Key definitions to memorise:

Implicit dependency: automatic from referencing another resource.

Explicit dependency: manual using depends_on.

Resource address: type.name or type.name[index].

create_before_destroy: creates new resource before destroying old one.

prevent_destroy: prevents any destruction of the resource.

ignore_changes: ignores specific attribute changes.

Trap patterns to watch for:

Confusing implicit vs. explicit dependencies.

Thinking create_before_destroy prevents destruction.

Using depends_on when implicit works.

Forgetting that resources with count use zero-based indexing.

Assuming lifecycle rules apply globally.

Key Takeaways

Terraform automatically creates resources in the correct order using implicit dependencies, which are derived from references in the configuration.

Use `depends_on` only for dependencies that Terraform cannot detect, such as side effects or external interactions.

Resource addressing uses the format `type.name` for single resources and `type.name[index]` for resources created with `count` or `for_each`, with indexing starting at zero.

`create_before_destroy` ensures zero-downtime updates by creating the new resource before destroying the old one, but the old resource is eventually removed.

`prevent_destroy` acts as a safety lock to stop Terraform from destroying a resource, but it does not prevent manual deletion in the cloud console.

`ignore_changes` is a targeted instruction that makes Terraform ignore specific attribute changes, not the entire resource.

Easy to Mix Up

These come up on the exam all the time. Here's how to tell them apart.

Implicit Dependency

Automatically created by Terraform when you reference a resource's attribute.

No extra code required; keeps configuration clean.

Covers most dependency cases.

Explicit Dependency (depends_on)

Manually added using the `depends_on` argument.

Makes the relationship visible but adds verbosity.

Only needed for non-obvious, side-effect dependencies.

create_before_destroy

Creates new resource before destroying old one.

Reduces or eliminates downtime during updates.

Old resource is eventually destroyed after new one is ready.

prevent_destroy

Prevents any destruction of the resource via Terraform.

Acts as a safety lock for critical data or components.

Does not affect creation or updates, only destruction.

Resource Addressing (single resource)

Format: `type.name` (e.g., `aws_instance.web`).

Useful for referencing a unique resource.

No index needed.

Resource Addressing (with count/for_each)

Format: `type.name[index]` (e.g., `aws_instance.web[0]`).

Indexing starts at zero.

Used to target individual instances from a group.

ignore_changes

Skips specific attributes when comparing config to real state.

Useful when manual or external changes are expected.

Does not ignore the whole resource, only listed attributes.

lifecycle customisation without ignore_changes

Manages all attributes defined in the configuration.

Will revert any divergence, even if done manually.

No exceptions; all attributes are kept in sync.

Watch Out for These

Mistake

Terraform always creates resources in the order they appear in the configuration file, from top to bottom.

Correct

Terraform creates resources based on the dependency graph it builds, not the order in the file. It analyses references to determine the correct creation order.

Configuration files are for human readability, not for execution order. People naturally assume order of writing equals order of execution, but Terraform uses a graph to parallelise and schedule resources.

Mistake

If I set `prevent_destroy = true`, the resource can never be deleted by anyone, even manually in the cloud console.

Correct

`prevent_destroy` only prevents Terraform from destroying the resource. Anyone with access to the cloud provider's console or API can still delete it outside of Terraform.

Beginners often think Terraform's controls lock down the cloud provider completely, but Terraform only manages resources it knows about. Manual actions bypass Terraform.

Mistake

Using `ignore_changes` means Terraform will ignore any changes to the resource entirely.

Correct

`ignore_changes` only ignores changes to the specific attributes listed. Other changes (like a new tag) are still detected and applied.

The word 'ignore' is vague. People think it ignores the whole resource, but it is a targeted instruction for specific attributes only.

Mistake

You must create an explicit dependency using `depends_on` for every relationship between resources.

Correct

The majority of dependencies are implicit, created automatically when you reference one resource's attribute in another. `depends_on` is only needed for non-obvious, side-effect dependencies.

New learners often overuse `depends_on` because they do not trust Terraform's automatic detection. The exam tests that implicit dependencies are the norm.

Mistake

If I use `create_before_destroy = true`, Terraform will never destroy the old resource.

Correct

`create_before_destroy` still destroys the old resource after creating the new one. It just changes the order to avoid downtime. The old resource is removed after the new one is healthy.

The phrase 'create before destroy' makes it sound like the old resource survives forever, but it is a temporary overlap. The old resource is eventually destroyed.

Do You Actually Know This?

Reveal each answer, then mark whether you got it right. Score 60%+ to unlock the next chapter.

Frequently Asked Questions

What is the difference between implicit and explicit dependencies in Terraform?

Implicit dependencies are automatically created when you reference one resource's attribute in another. Explicit dependencies are manual using the `depends_on` argument. Implicit is preferred; explicit is only for cases where Terraform cannot infer the relationship.

When should I use `depends_on` instead of implicit dependencies?

Use `depends_on` when a resource relies on something that is not directly referenced in its configuration, like a provisioning action (e.g., an Ansible playbook that must run after a database is seeded). It is a fallback for non-obvious dependencies.

Does `create_before_destroy` prevent the old resource from being deleted?

No, `create_before_destroy` changes the order so the new resource is created first, but the old resource is still destroyed after the new one is ready. It does not preserve the old resource indefinitely.

What does `ignore_changes` actually do?

`ignore_changes` stops Terraform from trying to revert changes to the attributes you list. For example, if you set `ignore_changes = [tags]`, Terraform will not update tags even if they differ from your configuration. Other attributes are still managed.

Can I set `prevent_destroy` on a data source?

No, `prevent_destroy` only works on resources, not data sources. Data sources are read-only and do not manage lifecycle. If you try, Terraform will give an error.

How do I reference a specific instance when using `count` to create multiple resources?

Use the index in square brackets, starting from zero. For example, `aws_instance.web[0]` is the first instance, `web[1]` is the second, and so on. This is called resource addressing.

Terms Worth Knowing

Keep going

You've finished Resource Dependencies and Lifecycle Management. Continue through the TF-003 study guide to build a complete picture of the exam.

Done with this chapter?