Safeguard
Security Guides•

When should a Terraform module live in its own repository?

A Terraform module deserves its own repository once several configurations reuse it. Here is how to decide, and what it changes for review and releases.

Safeguard Security Team
4 min read

Give a Terraform module its own repository when several configurations will reuse it and you want to release it on a schedule that differs from the code that calls it. Keep it local to the calling repository when only one stack uses it. HashiCorp's guidance points the same way.

What the documentation says

HashiCorp's module development page says that if many configurations will reuse a module, you should consider placing it in its own version control repository. It also warns against over-using modules, because they can make a configuration harder to understand and maintain.

The same page cautions against thin wrappers, which are modules that only wrap one resource type. If you struggle to name a module differently from the resource inside it, the module probably adds no abstraction and the calling code should use the resource directly.

Why this is a security question

A shared module is code that many teams run with their own credentials. A change to it reaches every caller that does not pin a version. So the question of where it lives is really a question of who can change it and how callers hear about the change.

A module inside an application repository inherits that repository's reviewers, which may be the wrong people. A module in its own repository can have its own owners, its own approval rules and its own tags. That separation is what makes tight review practical.

A decision table

SituationSuggested home
One stack uses it, one team owns bothLocal folder in the calling repository
Two or three stacks, same teamLocal folder, revisit when a third team appears
Several teams call itOwn repository with tagged releases
It encodes a security baseline (network, IAM, logging)Own repository with named owners
It wraps a single resource with no extra logicNo module, use the resource

What changes when you split it out

Moving a module into its own repository adds some overhead, and it is worth knowing the cost before you start.

  1. Callers switch from a relative path to a registry or git source, and must pin it. See pinning Terraform modules.
  2. You need a release habit. Tags should be semantic versions, and the public registry requires that format.
  3. You need owners for the repository, with review rules that match its blast radius. CODEOWNERS for workflow and release files is a good place to start.
  4. You need a way to tell callers about breaking changes, such as release notes and a clear major version bump.

Docs also note that examples inside a module repository should use the external address a caller would use, not a relative path, because examples get copied elsewhere.

A middle path

If a split feels premature, keep the module in a modules/ folder of a shared infrastructure repository with its own CODEOWNERS entry. You get separate reviewers without separate release machinery. Move it out when callers outside that repository need it.

Where Safeguard fits

Safeguard can enforce policies and gates on pull requests, including those to infrastructure repositories, and its compliance and evidence automation can record who approved a change. It does not replace choosing sensible owners. You can run a free scan at gold.safeguard.sh/scan.

Quick check

Is one module per repository required?

No. Terraform allows modules in subfolders or remote repositories. A separate repository is a design choice that helps when many configurations reuse a module.

Should every resource get a module?

No. HashiCorp advises against thin wrappers around a single resource type, because they add indirection without adding an abstraction.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.