Contents

Organizing Terraform Modules

As Terraform projects grow in complexity, organizing your modules effectively becomes critical to maintaining clean, reusable, and scalable infrastructure code. How you choose to organize these modules can significantly impact collaboration, code reuse, and overall project maintainability. In this blog post, we will explore three primary approaches to organizing Terraform modules: using local modules, storing all modules in one remote repository, and distributing modules across multiple remote repositories. We’ll discuss the benefits and limitations of each approach, with practical examples to help you decide which strategy best suits your needs.


Terraform modules are reusable packages of Terraform configurations that allow you to encapsulate and abstract infrastructure components. By leveraging modules, you can avoid redundancy, promote code reuse, and simplify complex infrastructure setups. Modules can be stored locally within your project directory or remotely in repositories, making them accessible to different teams and projects.


In the local modules approach, modules are stored directly within the project directory. This is a straightforward setup, where each module is defined in its own directory within the project structure. Local modules are referenced using relative paths.

  • Simplicity: Easy to set up and manage, especially for small projects.
  • No External Dependencies: Since modules are stored locally, there’s no need to configure remote repositories or authentication.
  • Quick Iteration: Changes to modules can be quickly tested and applied within the same project.
  • Limited Reusability and Duplication: Modules are tightly coupled with the project, making them harder to reuse across different projects.
  • Scaling Challenges: As your infrastructure grows, managing all modules within a single project can become unwieldy.
  • Difficult Versioning: Versioning local modules becomes difficult or impractical when they are stored within the same repository as the project code, leading to challenges in managing updates, dependencies, and stability across different environments.
  • Small Projects: Ideal for small projects where modularity is needed but code reuse across multiple projects is not a priority.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
/my-terraform-project
  ├── main.tf
  ├── variables.tf
  ├── outputs.tf
  ├── provider.tf
  └── modules/
      ├── vpc/
      │   ├── main.tf
      │   ├── variables.tf
      │   └── outputs.tf
      ├── ec2/
      │   ├── main.tf
      │   ├── variables.tf
      │   └── outputs.tf
      └── rds/
          ├── main.tf
          ├── variables.tf
          └── outputs.tf

In this approach, all Terraform modules are stored in a single remote repository. This centralized repository contains all the modules that can be shared across multiple projects. Modules are versioned and accessed using their repository URL, allowing different teams or projects to pull in the necessary modules.

  • Centralized Management: All modules are in one place, making it easier to maintain and apply consistent standards.
  • Reusability: Modules can be reused across multiple projects, reducing redundancy and promoting best practices.
  • Versioning Supported: Each module can be versioned by tagging the repository, allowing you to control updates and ensure stability across projects.
  • No Module Version Operator Support: With github modules only exact versions are supported when referencing a module within Terraform. That makes it challenging to propagate fixes and security patches applied to the module.
  • Complex CI/CD Workflows: Managing CI/CD pipelines for a repository containing multiple modules can become complex, make the workflows harder to maintain.
  • Medium to Large Teams: Suitable for organizations with multiple teams working on different projects, where code reuse and consistent standards are important.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
/terraform-modules-repo
  ├── vpc/
  │   ├── main.tf
  │   ├── variables.tf
  │   └── outputs.tf
  ├── ec2/
  │   ├── main.tf
  │   ├── variables.tf
  │   └── outputs.tf
  └── rds/
      ├── main.tf
      ├── variables.tf
      └── outputs.tf

In the multiple remote repositories approach, each module is stored in its own remote repository. This decentralized method gives each module its own lifecycle, making it easier to manage and version independently. Projects reference the necessary modules using their respective repository URLs.

  • Autonomy: Teams can manage module lifecycles separately, allowing for more tailored updates and improvements.
  • Scalability: This approach scales well as the number of modules grows, preventing any single repository from becoming too large.
  • Enhanced Versioning Control: Enables full support for semantic versioning and version operators within Terraform by allowing modules to be published individually to the Terraform Registry. This makes it easier to push critical security patches, fixes, and feature updates while ensuring that projects can specify and lock in exact module major or minor versions. This approach improves stability and provides safer, more controlled updates across environments.
  • Increased Overhead: Managing multiple repositories can lead to additional administrative and development overhead, primarily due to the need for frequent context switching between repositories. This can complicate tasks such as coordinating updates, setting up CI/CD pipelines, and maintaining consistency across modules, ultimately requiring more effort and time from the development team.
  • Large Organizations: Ideal for large organizations with multiple teams working independently on different components of the infrastructure, where module autonomy and scalability are priorities.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
/vpc-module-repo
  ├── main.tf
  ├── variables.tf
  └── outputs.tf

/ec2-module-repo
  ├── main.tf
  ├── variables.tf
  └── outputs.tf

/rds-module-repo
  ├── main.tf
  ├── variables.tf
  └── outputs.tf

The choice between local modules, one remote repository, and multiple remote repositories depends on several factors, including the size of your team and the complexity of your infrastructure.

  • Local Modules: Best for small projects or teams that do not require module reuse across multiple projects.
  • One Remote Repository: A good fit for medium to large teams that need centralized management of modules and consistent practices across projects.
  • Multiple Remote Repositories: Ideal for large organizations that require modular autonomy, scalability, and independent lifecycle management of each module.

Organizing Terraform modules is a key aspect of maintaining a clean, scalable, and efficient infrastructure as code practice. Whether you opt for local modules, a single remote repository, or multiple remote repositories, each approach has its own benefits and trade-offs. Understanding these options will help you choose the right strategy for your team and project, ensuring that your Terraform code remains maintainable, reusable, and adaptable as your infrastructure grows.

Happy engineering!