Dependency inversion with modules in Terraform - Time & Space Complexity
Start learning this pattern below
Jump into concepts and practice - no test required
We want to understand how the time to apply Terraform changes grows when using modules that depend on each other.
Specifically, how does adding more modules affect the number of operations Terraform performs?
Analyze the time complexity of this Terraform module dependency setup.
module "network" {
source = "./modules/network"
}
module "database" {
source = "./modules/database"
depends_on = [module.network]
}
module "app" {
source = "./modules/app"
depends_on = [module.database]
}
This sequence shows three modules where each depends on the previous one, creating a chain of dependencies.
Look at what Terraform does repeatedly when applying this setup.
- Primary operation: Terraform plans and applies each module in order, waiting for dependencies to finish.
- How many times: Once per module, but each module waits for the previous one to complete.
As you add more modules in a chain, Terraform must process each one after the previous finishes.
| Input Size (n) | Approx. API Calls/Operations |
|---|---|
| 3 | 3 (one per module) |
| 10 | 10 (one per module) |
| 100 | 100 (one per module) |
Pattern observation: The number of operations grows directly with the number of modules.
Time Complexity: O(n)
This means the time to apply grows linearly as you add more modules in a dependency chain.
[X] Wrong: "Adding more modules won't affect apply time because Terraform runs everything in parallel."
[OK] Correct: When modules depend on each other, Terraform waits for one to finish before starting the next, so time adds up.
Understanding how dependencies affect execution time helps you design efficient infrastructure and explain your choices clearly.
"What if all modules were independent with no depends_on? How would the time complexity change?"
Practice
Solution
Step 1: Understand module dependency principle
Dependency inversion means modules should not create resources directly but rely on inputs.Step 2: Identify correct description
Modules depend on inputs instead of creating resources themselves correctly states modules depend on inputs, making them flexible and reusable.Final Answer:
Modules depend on inputs instead of creating resources themselves -> Option BQuick Check:
Dependency inversion = Modules use inputs [OK]
- Thinking modules must create all resources internally
- Assuming modules cannot accept variables
- Believing modules must be in root config
Solution
Step 1: Identify correct variable passing syntax
Modules accept variables by name; the value can be a resource attribute like aws_instance.example.id.Step 2: Check option correctness
module "example" { instance_id = aws_instance.example.id } correctly passes instance_id with the resource ID aws_instance.example.id.Final Answer:
module "example" { instance_id = aws_instance.example.id } -> Option DQuick Check:
Pass resource ID as variable = module "example" { instance_id = aws_instance.example.id } [OK]
- Using undefined variable names like resource_id or input_id
- Passing resource IDs without variable names
- Confusing variable and resource references
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
}
module "network" {
source = "./modules/network"
vpc_id = aws_vpc.main.id
}What is the expected behavior of the
network module?Solution
Step 1: Analyze root module resource and module call
The root module creates an aws_vpc resource and passes its ID to the network module as vpc_id.Step 2: Understand module behavior with input
The network module uses the passed vpc_id to configure resources inside that VPC, not create a new one.Final Answer:
It uses the existing VPC ID passed as input -> Option CQuick Check:
Module uses input vpc_id = It uses the existing VPC ID passed as input [OK]
- Assuming module creates a new VPC ignoring input
- Thinking passing resource IDs is invalid
- Believing module fails without explicit VPC creation
module "db" {
source = "./modules/db"
subnet_id = aws_subnet.app.id
}Inside the module, the variable is declared as
variable "subnet" { type = string }. What error will occur?Solution
Step 1: Compare variable name and input argument
The module expects a variable named 'subnet' but the input is 'subnet_id'.Step 2: Understand Terraform variable matching
Terraform matches input arguments to variable names exactly. 'subnet_id' does not match any variable, causing an unsupported argument error.Final Answer:
Error: Unknown variable 'subnet_id' in module -> Option AQuick Check:
Variable name mismatch causes unknown variable error [OK]
- Assuming variable names can differ
- Confusing variable name with resource attribute name
- Ignoring error messages about missing variables
Solution
Step 1: Understand dependency inversion for modules
Modules should not create dependent resources like VPCs but accept them as inputs.Step 2: Evaluate options for best practice
Module accepts a VPC ID as input and creates security group in that VPC accepts VPC ID as input and creates the security group inside that VPC, following dependency inversion.Final Answer:
Module accepts a VPC ID as input and creates security group in that VPC -> Option AQuick Check:
Pass dependencies as inputs for flexibility [OK]
- Hardcoding resource IDs inside modules
- Modules creating dependent resources themselves
- Requiring users to create resources outside without module help
