Thuta Learning
IntermediateDevOpsintermediate

Modules

Relax. We'll talk through this in plain words — no textbook voice.

What you'll walk away with

  • Understand Modules without any of the intimidation
  • Get hands-on running terraform commands and HCL code yourself
  • Apply this concept in a real project right away

Let's think about it this way for a second

If you manually copy-paste the server + database + network setup for all three environments (dev/staging/prod), you end up maintaining nearly identical code in three places, which is error-prone — find one bug and you have to fix it in all three spots. A module lets you write that code once, like a function, and call it with `module "name" { source = "./path"; input = value }` — dev, staging, and prod can all call the same module while passing different values for things like instance_size and environment name. A module's inputs are defined with variable blocks, and its outputs with output blocks.

Let's connect this to a real scenario

You can put `main.tf` (resources), `variables.tf` (inputs), and `outputs.tf` (outputs) inside a `modules/web-app/` folder, then in the root config call it twice with `module "dev" { source = "./modules/web-app"; instance_type = "t3.micro" }` and `module "prod" { source = "./modules/web-app"; instance_type = "t3.large" }` — no need to write the code inside the module twice.

Let's look at it together

hcl
# modules/web-app/main.tf
variable "instance_type" {
  type = string
}

resource "aws_instance" "web" {
  ami           = "ami-0abcdef1234567890"
  instance_type = var.instance_type
}

output "public_ip" {
  value = aws_instance.web.public_ip
}

# root main.tf
module "dev" {
  source        = "./modules/web-app"
  instance_type = "t3.micro"
}

module "prod" {
  source        = "./modules/web-app"
  instance_type = "t3.large"
}
You should see
$ terraform apply
module.dev.aws_instance.web: Creating...
module.prod.aws_instance.web: Creating...

Apply complete! Resources: 2 added, 0 changed, 0 destroyed.

5-minute try-it

Create a `modules/web-app/` folder (split into variables.tf, main.tf, outputs.tf), then call it twice from the root config, passing a different instance_type each time.

A quick word of caution

Changing a module and applying it can affect every environment that calls that module — test in staging before changing a production module.

Easy traps

  • Calling a module without a default value for an input variable and without passing a value from the root config — resulting in an error
  • Hardcoding values (region, instance_type) inside a module — the whole point of a module is reusability, and hardcoding kills that

Now try it yourself

Create a `modules/web-app/` folder (split into variables.tf, main.tf, outputs.tf), then call it twice from the root config, passing a different instance_type each time.

You'll know it worked when: $ terraform apply module.dev.aws_instance.web: Creating... module.prod.aws_instance.web: Creating... Apply complete! Resources: 2 added, 0 changed, 0 destroyed.