Terraform Modules, Variables & Data Sources – The Building Blocks of IaC!

If you're new to Terraform or Infrastructure as Code (IaC), you might wonder:
✅ How do we make our Terraform code reusable?
✅ How can we avoid hardcoding values?
✅ How do we fetch existing infrastructure details dynamically?
The answer lies in Modules, Variables, and Data Sources! Let’s break them down in the simplest way.
📦 Terraform Modules – Think of Them as Lego Blocks!
A Terraform module is just a collection of reusable code. Instead of writing the same Terraform configuration multiple times, you can package it into a module and use it anywhere!
🔹 Why use modules?
✔️ Avoid repetition by reusing code
✔️ Organize infrastructure into logical components
✔️ Make Terraform projects scalable and maintainable
🔹 Example:
Instead of writing separate Terraform code for each EC2 instance, you can create an "EC2 Module" and reuse it for multiple servers.
How to use a module?
module "webserver" {
source = "./modules/ec2"
instance_type = "t2.micro"
ami_id = "ami-12345678"
}
Here, ./modules/ec2
contains reusable EC2 instance configuration.
🔢 Terraform Variables – Say Goodbye to Hardcoding!
Variables in Terraform allow us to pass dynamic values instead of writing fixed values in the code.
🔹 Why use variables?
✔️ Make your code flexible and reusable
✔️ Easily change values without modifying the code
✔️ Store sensitive data securely
🔹 Example:
Instead of hardcoding an AWS region:
variable "aws_region" {
default = "us-east-1"
}
You can now use it anywhere like this:
provider "aws" {
region = var.aws_region
}
Pro Tip: Use terraform.tfvars
to store variable values for different environments like dev, staging, and production!
🔍 Terraform Data Sources – Fetch Existing Infrastructure!
A data source in Terraform helps you retrieve existing resources instead of creating them from scratch.
🔹 Why use data sources?
✔️ Fetch details of existing cloud resources
✔️ Avoid duplication of infrastructure
✔️ Integrate Terraform with manually created or external resources
🔹 Example:
Instead of manually entering the latest AWS AMI ID, you can fetch it dynamically:
data "aws_ami" "latest_amazon_linux" {
most_recent = true
filter {
name = "name"
values = ["amzn2-ami-hvm-*"]
}
owners = ["amazon"]
}
Now, you can use this AMI ID dynamically in your EC2 instance creation:
resource "aws_instance" "web" {
ami = data.aws_ami.latest_amazon_linux.id
instance_type = "t2.micro"
}
This way, your infrastructure always uses the latest Amazon Linux AMI without manual updates!
💡 Key Takeaways
✅ Modules make Terraform code reusable and organized
✅ Variables help avoid hardcoding and make Terraform flexible
✅ Data sources allow Terraform to fetch existing infrastructure
With these, you can write cleaner, more scalable, and efficient Terraform code!
📢 What’s your biggest challenge with Terraform? Let’s discuss! 👇
Subscribe to my newsletter
Read articles from Sandeep Naidu directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Sandeep Naidu
Sandeep Naidu
Cloud & DevOps Engineer| SRE | Kubernetes | AWS | Ansible | GIT | Terraform | Gitlab | Docker | Python