Terraform Basics #4 - Modules

Last Edited: 10/7/2025

This blog post introduces modules in Terraform.

DevOps

In the previous article, we discussed variables and outputs in HCL, which enable flexible and reusable infrastructure configuration management and provisioning in Terraform. However, there's another powerful concept in Terraform called modules, which provides another layer of abstraction and contributes to having cleaner and more reusable Terraform code. In this article, we's discuss how to use and build modules effectively for even more effective organization and seamless provisioning of infrastructure resources in Terraform.

Modules

A module can easily be created by organizing resource and variable .tf files into a directory. Typically, we organize different types of resources like databases, networks, and compute resources into separate files such as database.tf, network.tf, and compute.tf. A local module can then be loaded and utilized using the relative path to the directory, as follows.

main.tf
module "web_app" {
  source = "../web_app_module"
 
  # Input Parameters
  bucket_name      = "web_app_1"
  domain           = "example.com"
  app_name         = "web_app_1"
  environment_name = "production"
  # ...
}

Applying the above will create the resources defined in the local module within the web_app_module subdirectory, according to the input parameters and meta-arguments provided in the module block. The source argument also accepts links to Terraform module repositories hosted on GitHub, the Terraform Registry, and other remote hosting services. When modules are defined with appropriate levels of abstraction, they can prevent the duplication of work involved in defining complex infrastructures and allow developers to easily customize them for different applications.

Managing Multiple Environments

Modules are particularly useful for managing different environments, such as development, staging, and production. Typically, we set up directories like dev, staging, and production, each containing a main.tf file that references global modules and a terraform.tfvars file for configuring input parameters. Terraform's workspace feature can also be used to manage different environments, allowing users to switch between them using the same codebase and backend. However, using modules is generally preferred because they provide better backend isolation for enhanced security and a more explicit codebase that fully represents the deployed state, reducing the risks of human error.

CI/CD Pipeline

As mentioned previously, one of the most important benefits of Terraform is that it can be version controlled and seamlessly integrated into CI/CD workflows like GitHub Actions. We can set up a workflow triggered on push to the main branch to test the staging environment setup, and another workflow triggered by a release event to deploy the global production environment, automating the testing and deployment of infrastructure resources. Conveniently, HashiCorp provides a public GitHub Action for setting up Terraform, hashicorp/setup-terraform@v1, that can be used for this purpose.

For testing, we could check the formatting with terraform fmt --check and verify that the planning succeeds with terraform plan. Then, we can write and run a bash script that temporarily creates resources and checks their availability. Alternatively, if you are familiar with Go, you could write a Go script using the Terratest library by Gruntwork. If all tests pass, the resources can be deployed using terraform apply -auto-approve on modules and on resources in the corresponding environment. Since out-of-band changes via CLI and GUI are major causes of conflicts and errors, it's advisable to set up CI/CD workflows and restrict changes to be made only through Terraform.

Conclusion

In this article, we introduced modules and how they can be utilized to take full advantage of Terraform as an Infrastructure-as-Code tool. This concludes our short Terraform series (at least for now). I highly recommend using modules to rewrite the Terraform code from the previous article for practice and in other projects. For more details and explanations, I highly recommend checking out the resources cited below.

Resources