Why I choose Monorepo over Polyrepo all the time for IaC


How to choose between monorepo vs polyrepo for IaC projects.

IaC
Intermediate
Published: May 21, 2026 13 min read

Where does all this code live?

This is the question that you've got to ask yourself, before starting an IaC project.

In the early days of cloud migration, IaC was often treated as a collection of loose scripts—ancillary code tucked away in an administrator's folder or tossed into a repository as an afterthought. Today, IaC is production software. It governs security boundaries, routing tables, and data persistence layers. Because it is software, it demands the same architectural discipline as our application code, starting with repository layout.

As engineering organizations scale, they inevitably hit a fork in the road, forcing a choice between two primary repository strategies: Monorepo **vs **Polyrepo

Defining the Strategies Monorepo **vs **Polyrepo

Before diving into the operational friction of state management and pipeline constraints, we need to establish exactly what these strategies look like when applied to tools like Terraform, OpenTofu, or AWS CloudFormation.

The distinction between these two architectures comes down to how you draw boundaries around your code, your state files, and your deployment pipelines.

The Infrastructure Monorepo

In an IaC monorepo, a single version-control repository houses every piece of infrastructure code for the entire organization. It acts as the single source of truth for all environments (Development, Staging, Production) and all shared resources.

Instead of relying on repository boundaries to separate concerns, a monorepo relies entirely on strict directory structures and workspace logic. A standard Terraform or OpenTofu monorepo typically looks like this:

text
infrastructure-monorepo/
├── .github/workflows/          # Centralized CI/CD pipelines for all infrastructure
├── modules/                    # Shared, reusable resource configurations
│   ├── aws-vpc/
│   └── aws-rds/
└── environments/               # Live infrastructure states
    ├── dev/
    │   ├── main.tf             # Calls local modules (e.g., source = "../../modules/aws-vpc")
    │   └── backend.tf          # Points to the dev-specific state file
    └── prod/
        ├── main.tf             
        └── backend.tf          # Points to the prod-specific state file

In this model, any engineer can see the entire infrastructure tree. When a change is made to the aws-vpc module, a single Git commit can test and propagate that change across both the dev and prod environments simultaneously.

The Infrastructure Polyrepo

The polyrepo strategy takes the opposite approach: it aggressively decouples infrastructure into multiple, independent repositories.

These repositories are typically split along architectural fault lines—such as lifecycle speed, blast radius, or team ownership. Core networking (which changes rarely and requires high security) is physically separated from application infrastructure (which changes daily). Shared modules are also extracted into their own repositories and versioned independently.

A typical polyrepo architecture looks like a collection of distinct Git projects:

text
# Repository 1: Shared Modules 
iac-tf-modules/                 
├── vpc/
└── rds/
# -> Consumers reference this via Git tags: source = "git::...//vpc?ref=v1.2.0"

# Repository 2: Core Networking
iac-network-prod/               
├── .github/workflows/          # Independent pipeline for core network
├── main.tf                     # VPC, Subnets, Transit Gateway
└── backend.tf                  # Isolated core network state file

# Repository 3: Platform Compute
iac-eks-clusters-prod/          
├── .github/workflows/          # Independent pipeline for Kubernetes
├── main.tf                     # EKS control plane and node groups
└── backend.tf                  # Isolated EKS state file

In this model, isolation is the primary feature. The pipeline executing changes against iac-eks-clusters-prod operates completely blind to the iac-network-prod repository. To use the shared modules, downstream repositories must explicitly pin specific version tags, forcing a deliberate upgrade process rather than implicitly inheriting local changes.

The Monorepo Deep Dive: The "Everything Bagel"

Operating inside an IaC monorepo feels highly fluid. Because all of your infrastructure definitions, shared modules, and environment states live in a single tree, you have an unobstructed view of your entire cloud footprint. This centralized approach acts as an "everything bagel," offering massive conveniences but requiring strict operational discipline to prevent chaos.

Here is a look at where the monorepo architecture shines—and where it starts to break down.

The Strengths: Speed and Visibility

  • Atomic Changes & Rapid Refactoring: This is the monorepo’s superpower. Because environments reference shared modules via local relative paths (e.g., source = "../../modules/aws-vpc"), you can update a module and immediately see the impact across Dev, Staging, and Prod in a single terraform plan. If you need to add a new tagging variable to every S3 bucket in your organization, you can execute and review that change in one cohesive Pull Request.
  • Unified CI/CD Tooling: You only have to write and maintain your pipeline logic once. A single .github/workflows/terraform.yml file can orchestrate your security scanning (like Checkov or Tfsec), linting, planning, and applying. You don't have to chase down pipeline updates across dozens of repositories.
  • Discoverability & Code Reuse: When everything is in one place, engineers can easily search the codebase to see how a specific problem was solved in another environment. This naturally reduces duplicated effort and encourages the use of standardized modules.

The Operational Friction: Scaling Pain Points

  • The "Blast Radius" Risk: In a monorepo, pipeline mistakes can be catastrophic. If your CI/CD path-filtering logic is flawed, a commit intended to tweak a development IAM role could accidentally trigger a run against the production environment. You are entirely reliant on smart path-filtering (e.g., executing only if changes occur in environments/dev/) and tools like Atlantis or Terragrunt to safely contain the deployment scope.
  • Concurrence and Lock Contention: As your engineering team grows, the monorepo can become a bottleneck. If five engineers open PRs at the same time, CI pipelines will attempt to run terraform plan concurrently. Depending on your state backend configuration, this often leads to state lock contention—where one pipeline fails or waits indefinitely because another is currently holding the state lock.
  • Complex Access Control: Standard Git permissions are binary; you either have write access to the repository, or you don't. In a monorepo, a junior engineer needs write access to deploy to Dev, but that same access technically allows them to modify Prod code. To enforce compliance, you must layer on robust branch protection rules, complex CODEOWNERS files to mandate specific approvals for production directories, or policy-as-code tools (like Open Policy Agent) to validate changes before they merge.

The Polyrepo Deep Dive: "Islands of Isolation"

If the monorepo is the "everything bagel," the polyrepo is a collection of high-security safety deposit boxes. By breaking infrastructure down into multiple, isolated repositories, you enforce hard physical boundaries between your environments, architectural layers, and teams.

This architecture trades the speed of sweeping, global changes for predictability, security, and strict access control.

The Strengths: Boundaries and Simplicity

  • Minimized Blast Radius: In a polyrepo, isolation is guaranteed by the version control system itself. A developer making a catastrophic mistake in the CI/CD pipeline of the iac-app-dev repository cannot accidentally destroy the production database because the production state and code physically exist in a separate repository (iac-database-prod). The blast radius is naturally constrained to the repository's scope.
  • Simple, Native Access Control: You do not need complex CODEOWNERS files, directory-level parsing, or custom Open Policy Agent (OPA) rules to restrict access. You can leverage standard GitHub, GitLab, or Bitbucket role-based access control (RBAC). A junior developer gets full read/write access to the Dev repository and zero access to the Prod repository. It satisfies strict compliance and auditing requirements (like SOC2) effortlessly.
  • Decoupled, Lightning-Fast Pipelines: Because each repository only contains the code for a specific component, CI/CD pipelines run significantly faster. There is no need for complex path-filtering logic to figure out what changed; if a commit is pushed to the repository, the pipeline runs a simple terraform plan on that exact directory. Lock contention drops dramatically because teams are no longer fighting over a single central pipeline queue.

The Operational Friction: Sprawl and Drift

  • Dependency "Hell" and Version Drift: The isolation of a polyrepo makes cross-cutting changes incredibly tedious. If you identify a security vulnerability in your core aws-vpc module and patch it, the fix does not automatically propagate. Because consumer repositories use Git tags to reference modules (e.g., source = "git::...//vpc?ref=v2.1.0"), you must open a separate Pull Request in every single repository that consumes that module to bump the version to v2.1.1. Without automation tools like Dependabot or Renovate, version drift is inevitable.
  • Tooling and Standard Fragmentation: When you have 50 different infrastructure repositories, you also have 50 different CI/CD pipeline files. If your security team decides to add Checkov to scan for misconfigurations, you have to update 50 repositories. While centralized pipeline templates (like GitHub reusable workflows or GitLab CI includes) can mitigate this, ensuring uniform linting, security, and tagging standards across a sprawling polyrepo ecosystem is a massive administrative burden.
  • Opaque Architecture: Discoverability suffers in a polyrepo. An engineer looking to understand how the network connects to the Kubernetes cluster and the database might have to clone and inspect three different repositories, piecing the architecture together mentally.

Technical Evaluation Matrix

When choosing a repository architecture for Infrastructure as Code, the decision ultimately comes down to which operational trade-offs your engineering team is equipped to handle.

This matrix compares the day-to-day realities of managing both architectures across five critical dimensions of infrastructure delivery.

Operational Factor Monorepo Realities Polyrepo Realities
State File Isolation Relies entirely on strict remote backend keys and disciplined directory structures. Naturally isolated; one repository maps directly to specific state files.
CI/CD Execution Requires advanced path-based filtering to ensure only modified directories trigger a run. Relies on standard push-to-branch triggers with fast, decoupled pipelines.
Access Control (IAM) Complex. Requires directory-level CODEOWNERS or policy-as-code to protect production. Simple. Leverages native Git repository-level permissions to enforce boundaries.
Module Versioning Leverages local relative paths, allowing shared module updates to apply instantly. Requires Git tags and independent Pull Requests to upgrade consuming repositories.
Blast Radius High. A misconfigured global workflow can accidentally impact stable environments. Low. Failures are physically constrained to the boundary of the specific repository.

Understanding these realities is only half the battle. The architecture you choose will heavily dictate the ecosystem of tools you need to support it.

The Tooling Factor: Enablers vs. Blockers

Your choice of repository architecture does not exist in a vacuum; it dictates the ecosystem of CI/CD and automation tools you must adopt to survive. The exact same deployment toolchain that makes a monorepo lightning-fast will completely fracture if applied to a sprawling polyrepo setup.

Whether your team is writing infrastructure in Terraform, OpenTofu, or bridging provisioning with configuration management tools like Ansible, success relies on matching the right tooling to your repository strategy.

Tools for the Monorepo Ecosystem

A monorepo requires tools that solve two primary problems: blast radius containment and selective execution. You cannot afford to run a full infrastructure evaluation on every single commit.

  • Smart Execution Engines (Terragrunt & Terramate): To keep code DRY (Don't Repeat Yourself) and manage complex dependencies between directories, tools like Terragrunt are practically mandatory in a monorepo. They allow you to define remote states dynamically and orchestrate runs across multiple environments efficiently.
  • GitOps PR Automation (Atlantis): In a monorepo, pipeline lock contention is a major bottleneck. Atlantis solves this by hooking directly into your Pull Requests. Developers type atlantis plan in a GitHub/GitLab comment, and Atlantis acquires the state lock, runs the plan specifically for the modified directory, and outputs the result back to the PR.
  • Strict Directory Validators: When mixing tools in a monorepo, strict directory compliance is critical for automated pipelines. For example, if you are incorporating configuration management, your CI/CD pipeline must enforce correct layouts—such as ensuring Ansible code includes the mandatory ansible_collections path, otherwise the pipeline will silently fail to discover your collections during deployment.
  • Path-Filtering CI/CD: If relying on native pipelines (like GitHub Actions or GitLab CI), you must leverage advanced path-filtering (e.g., paths: ['environments/prod/']) and parent-child pipelines to ensure a change in the development folder doesn't mistakenly trigger a production workflow.

Tools for the Polyrepo Ecosystem

A polyrepo removes the risk of blast radius but introduces massive sprawl. To support this architecture, your tooling must focus on dependency management and global visibility.

  • Automated Dependency Management (Renovate or Dependabot): Because a polyrepo relies on Git tags for shared modules, a single module update requires opening multiple PRs across your consumer repositories. Tools like Renovate automate this process, scanning your OpenTofu or Terraform files and automatically opening PRs to bump the module versions, keeping drift to a minimum.
  • Centralized Orchestration Platforms: Managing 50 isolated pipelines natively is an administrative nightmare. Platforms like Env0, Spacelift, or Terraform Cloud act as the control plane. They allow you to connect dozens of isolated polyrepos to a single centralized dashboard, enforcing global security policies (like Open Policy Agent rules) and tracking costs across all decoupled environments from one screen.
  • Security & Policy Scanners (Checkov / Tfsec / Trivy): In a polyrepo, you cannot rely on developers to manually configure security scans in every new repository. You must build custom pipeline templates or leverage organizational webhooks to inject tools like Checkov globally, ensuring no isolated repository bypasses compliance checks before reaching production.

Ultimately, you shouldn't choose an architecture without also committing to the specific operational tooling required to support it.

So, why I use Monorepo for all my projects

With the type of work I do and the teams I work with, I've found that Monorepo suits almost all of my projects. So, I have been using Monorepo all the time. If a need arise, I will not hesitate to use the Polyrepo approach.

You'd be better off by not choosing between monorepo or polyrepo based on technical superiority. Instead, let it be governed by Conway’s Law: your infrastructure repository architecture will inevitably mirror your organization's communication structures and team boundaries.

The "Hybrid" Reality

It is worth noting that many mature engineering organizations do not strictly adhere to one extreme. They often land on a highly effective hybrid model. For example, a team might maintain a polyrepo structure for their reusable AWS infrastructure modules—strictly versioning components like VPCs or IAM roles via Git tags—while utilizing a centralized monorepo to define the live environment states that consume those modules. This approach enforces safe module development while keeping environment visibility high.

The Final Verdict

Choose the Monorepo strategy if:

  • You have a single, tight-knit platform team managing the entire cloud footprint.
  • You want absolute consistency, rapid refactoring, and instant visibility across Dev, Staging, and Prod.
  • You are fully committed to adopting smart orchestration tools like Terragrunt, OpenTofu workspaces, or Atlantis to manage state locks and pipeline boundaries.

Choose the Polyrepo strategy if:

  • You are scaling a large enterprise with distinct, autonomous engineering teams that should not overlap.
  • You operate under strict regulatory and compliance requirements that demand hard, repository-level boundaries between development and production infrastructure.
  • You are moving toward a multi-repo architecture where infrastructure is decentralized and embedded directly alongside the application code it supports.

For aspiring DevOps engineers stepping into platform architecture roles, the most critical takeaway is this: do not choose a repository layout based on what works for a massive tech giant. Choose the layout that matches your team's current size, your security posture, and your CI/CD maturity.

The best infrastructure architecture is simply the one that allows your team to deploy safely, consistently, and without operational friction—no matter which folder the code lives in.

Indika Kodagoda

Indika Kodagoda

Indika Kodagoda is a Lead DevOps Engineer, AWS certification instructor, and the creator of CloudQubes. He specializes in cloud infrastructure, automation, and modern Ruby on Rails development. When he’s not deploying code or mentoring aspiring engineers, he’s usually enjoying nature and cycling local gravel paths.