The Monorepo Won
The polyrepo vs monorepo debate seemed like a draw for years. It isn't anymore. The tooling closed the scalability gap and AI development broke the balance.
For years the polyrepo vs. monorepo debate was a genuine draw. Both had real trade-offs. Monorepos offered shared tooling, atomic cross-service commits, and easier refactoring across boundaries. Polyrepos offered clear ownership, independent deployment cadences, and repositories that didn't take fifteen minutes to clone. Reasonable engineers landed in different places depending on their team size, tech stack, and pain tolerance.
That balance has shifted. The monorepo has won, and the two forces that settled it are the maturity of monorepo tooling and the rise of AI-assisted development.
Why the old objections were real
The case against monorepos at scale was not theoretical. Google and Meta could make monorepos work because they had internal tooling — Blaze, Buck — that almost no other organization could replicate. The average engineering team using a monorepo got the coordination benefits but also got: slow CI that ran every test on every change because the build system didn't know what actually needed to rebuild, git operations that degraded as history grew, unclear ownership when every team's code was adjacent to every other team's code, and deployment pipelines that had to figure out which services were affected by a given commit.
Polyrepos solved these problems by separation. Each repository was small, fast, and owned by one team. CI was scoped to a single service. Deployment was straightforward. The cost was coordination: cross-repo changes required coordinated PRs, dependency version management became a full-time job at some scale, and shared library updates propagated slowly and inconsistently.
Neither model was clearly superior. The pain was just distributed differently.
What the tooling solved
The critical change over the last several years is that the tooling gap closed. Nx, Turborepo, and Bazel have made build caching, affected-change detection, and parallel task execution available to ordinary engineering organizations without requiring a dedicated internal platform team.
Affected-change detection is the foundational capability. In a naive monorepo CI, every commit triggers every test. In a well-configured monorepo with dependency graph analysis, a commit to the authentication service triggers only the tests for the authentication service and the services that depend on it — which might be ten percent of the total. The build that used to take forty minutes takes four, and it takes four for the right reason: it's doing exactly the work required for the change that was made.
Build caching closes the remaining gap. Local task results — type checks, lints, test runs — are cached by input hash. If you run the same task with the same inputs, the cache returns the result instantly. Remote caches shared across the team and CI mean that CI rarely rebuilds what a developer just ran locally. The slow-clone problem is addressed by shallow clones and sparse checkouts, which git has supported for years but which monorepo tooling now orchestrates automatically.
The ownership problem is addressed by CODEOWNERS files and workspace-scoped access controls, which are now standard in most CI and repository platforms. A team can own a subtree of a monorepo with the same clarity of ownership they'd have in a dedicated repo, without the coordination overhead of cross-repo changes.
The AI development case
The second force is less often discussed but increasingly significant: AI-assisted development is inherently cross-cutting.
When a developer uses an AI code assistant to implement a feature that touches multiple services, the AI needs to understand the interfaces between those services. In a polyrepo setup, that understanding requires either loading multiple repositories into context — which is clunky, often incomplete, and requires the developer to manually assemble the relevant context — or making the AI work from documented interface contracts, which are usually stale.
In a monorepo, the relevant context is co-located. The AI tool can read the service it's modifying and the services it depends on in a single pass. It can see the actual interface definitions, the actual error handling patterns, the actual data models. The quality of AI-assisted code is meaningfully higher when the context is coherent and complete.
This matters more than it might seem. The productivity gain from AI-assisted development scales with context quality. A polyrepo organization using AI tools is providing those tools with fragmented context by default, and individual developers are constantly bridging that fragmentation manually. The coordination tax of polyrepo is partly absorbed by AI tools in a monorepo setup — the AI can make cross-service changes without the developer having to manually open multiple repositories, submit multiple PRs, and coordinate their merge order.
As AI assistance becomes more central to how code gets written, the architectural choice between monorepo and polyrepo has direct productivity implications, not just process implications.
What the monorepo does not solve
Choosing a monorepo is not a solution to team coordination, ownership conflicts, or unclear service boundaries. These problems exist in both models; the monorepo makes them more visible rather than hiding them behind repository boundaries, which is an improvement, but visibility is not resolution.
The monorepo also does not solve the dependency management problem by itself. Shared libraries in a monorepo still need versioning discipline if they're consumed by applications that need to be stable. The monorepo makes it easier to make breaking changes and easier to migrate consumers in the same commit, but it doesn't remove the need for discipline around what's stable and what's internal.
And the monorepo requires investment in tooling configuration to get the build-time benefits. A naive monorepo with no affected-change detection and no build caching is worse than a polyrepo on CI speed. The tools exist, they're not especially complex to configure, but they don't configure themselves.
The practical implications
For teams starting new projects today, the default should be a monorepo unless there is a specific reason for separation. The tooling is good enough that the historical objections to monorepos at scale have been substantially addressed. The benefits — atomic cross-service commits, shared tooling, easier refactoring, better AI assistance context — accrue immediately and compound over time.
For teams with existing polyrepos, the calculus depends on how much cross-repo change frequency they're experiencing and how heavily they're using AI assistance. High cross-repo change frequency is a strong signal that the services want to be co-located. High AI tool usage in a polyrepo context is a strong signal that developers are paying a context assembly tax daily.
The monorepo won not because it was always right. It won because the problems that made it impractical were solved, and the problems that make polyrepo increasingly costly are getting worse. That's what winning looks like in infrastructure debates — not a decisive argument, just accumulated evidence pointing in one direction until the other side runs out of viable objections.
Work with me
I consult with engineering teams on AI adoption, cloud architecture, and engineering effectiveness. If this post surfaced a challenge you're facing, let's talk.
Get in touch →Related posts
Explore more on these topics: