Skip to content

Monorepo vs Polyrepo: Architecture & Tradeoffs

Lesson 2 of 10Advanced16 min readGit at Scale & Enterprise Engineering · Large RepositoriesVerified: GitHub repository limits documentation, September 2026

There is no correct answer, and the people who tell you otherwise are describing an organisation whose constraints you may not share.

What there is: a set of forces that pull in opposite directions, and an organisation shape that makes one set dominant. This article is about identifying which forces apply to you.

Every argument in this space is one of these winning over the others.

Atomicity. Can a change spanning several components be one commit, one review, one merge?

Release independence. Can component A ship without component B being ready?

Ownership clarity. Is it obvious who is responsible for a given piece of code, and who should review a change to it?

Access control. Can you restrict who reads what?

Coordination cost. How many people must agree to make a routine change?

Tooling cost. How much machinery must you build and maintain?

Discoverability. Can an engineer find code they did not write?

Consistency. Do components share versions, standards and toolchains by construction or by discipline?

These do not agree. Atomicity and access control pull in opposite directions. Consistency and team autonomy pull in opposite directions. Every architecture is a resolution, and the question is which forces matter most in your organisation.

MonorepoPolyrepo
Cross-component changeOne pull requestN, with an ordering nobody enforces
Shared library upgradeAtomic, all consumers at oncePer consumer, on their own schedule
Release independenceRequires conventionBy construction
OwnershipCODEOWNERS, maintainedThe repository boundary
Read access controlNone below repository levelPer repository
DiscoverabilityEverything is on diskWhich repository?
Version consistencyOne version of everythingSkew is the normal state
CI scopingRequires path awareness or a build graphFree
Clone costThe whole estateJust this component
ToolchainShared by constructionPer team, diverges
Refactoring across componentsMechanicalA migration programme
Repository limitsApproachedNot a factor
Tooling investmentSubstantial and requiredModest
New-team onboardingOne clone, one setupFind and clone six repositories

Two rows are the crux. Atomicity is the strongest argument for a monorepo. Read access control is the strongest argument against, and it has no workaround — Git has no path-level read restriction and neither does GitHub.

The useful form of this question. Not “which is better” but “what fits this situation”.

A startup with twelve engineers and one product. One repository. Splitting introduces coordination overhead to solve a problem that does not exist, and the tooling investment a monorepo needs at scale is not needed at this size — a plain repository with no sparse checkout and no build graph works.

A company with two unrelated products. Two repositories, or two monorepos. Shared code between them, if any, is a published library. Forcing them together produces a shared CI pipeline and a shared branch budget for teams with nothing else in common.

A platform team plus twenty product teams, heavy code sharing. This is the monorepo’s home ground. The shared libraries change frequently, every change touches consumers, and atomicity is worth the tooling. The platform team exists to build the apparatus, which resolves the biggest objection.

Microservices with genuinely independent lifecycles. Polyrepo, usually. If services deploy independently, are owned by independent teams, and share only well-versioned interfaces, the repository boundary is doing useful work. A monorepo here gives you coordination cost with no atomicity benefit, because the changes were never atomic anyway.

Microservices that always ship together. A monorepo, and a hard question about whether they are microservices. Services that cannot deploy independently are a distributed monolith, and the repository structure is the least of it.

A regulated component alongside general code. Polyrepo for that component at minimum. Read-access control requires a repository boundary, and there is no way to achieve it inside one.

An organisation with contractors or agencies. Polyrepo for whatever they touch, for the same reason.

A mobile app with a backend. Frequently a monorepo, because the API contract changes across both and atomicity is genuinely valuable — a contract change and both sides of it in one reviewable commit. Frequently a polyrepo, because the toolchains share nothing, the app has its own release process governed by an app store review queue, and old app versions remain in the wild for months regardless of what the backend does. Both are common, and the deciding factor is usually how often the contract changes against how long old clients survive.

A machine-learning organisation. Depends entirely on the data. Models and datasets are large binaries that do not belong in Git at all, and once they are in object storage with a versioning scheme, the remaining code question is ordinary and answered by the criteria above. Teams that skip that step and put model weights in Git experience a repository problem so dominant that the monorepo question becomes irrelevant.

A company after an acquisition. Leave the acquired repositories where they are for at least a year. Merging repository structures during an integration adds a large project to an already large one, and the boundary is genuinely useful while two engineering cultures converge.

Common claims that do not survive examination.

“A monorepo means better code sharing.” It makes sharing possible without publishing a package. Teams still have to do it, and vendored copies inside monorepos are extremely common. Sharing is a culture outcome; the repository is a precondition.

“A polyrepo means better separation of concerns.” Repository boundaries do not enforce architectural boundaries. Two repositories can be as tangled as two directories, and the tangle is harder to see because no single view shows it.

“Monorepos do not scale.” Several of the largest engineering organisations run one. They scale with substantial tooling investment, which is the actual cost.

“Polyrepos are simpler.” Simpler per repository, and the estate is not — twenty repositories with twenty CI configurations, twenty dependency sets and twenty divergent conventions is not simple.

“We should split because clones are slow.” Almost always the wrong remedy. Slow clones are usually binaries or an absence of partial clone, and splitting a repository to fix a Git-performance problem is an expensive way to avoid a one-line change.

“We should merge because dependency management is painful.” Sometimes right. Also frequently a symptom of components that are too coupled to be separate services, in which case the repository structure is reflecting a real architectural problem rather than causing one.

Version skew is the polyrepo’s characteristic failure

Section titled “Version skew is the polyrepo’s characteristic failure”

Worth its own section, because it is the cost that accumulates invisibly.

In a monorepo there is one version of the shared library. Every consumer uses it. A breaking change is fixed everywhere in the same commit.

In a polyrepo, consumers are on whatever version they last upgraded to. After two years, twelve repositories are on nine versions. A security fix in the library reaches only whoever upgrades.

The costs:

A vulnerability requires a campaign. Twelve pull requests, twelve reviews, twelve teams to chase — and the answer to “are we patched” is a query rather than a fact.

Breaking changes never complete. The library maintainer supports old versions indefinitely because somebody is still on them.

Nobody knows the true dependency graph without building an inventory, which means the blast radius of a library change is unknown until something breaks.

The mitigations are real and partial. Automated dependency pull requests reduce the lag; they do not eliminate the skew, and a queue of eleven unmerged upgrade pull requests is a common sight. A published deprecation policy helps and requires enforcement.

This is the polyrepo cost that most often eventually prompts a monorepo migration, and it is worth pricing honestly before choosing.

The symmetrical honesty.

What a monorepo requires that a polyrepo does not:

Path-aware CI, or every change runs everything. Sparse checkout tooling, once the working tree exceeds what people want on disk. A build graph, once path filtering stops being precise enough. CODEOWNERS discipline, because the repository boundary is not doing ownership any more. Branch and tag hygiene, because GitHub’s 5,000-branch limit is reachable when every team’s branches land in one repository. Release conventions, because tags are repository-wide.

Each is a system somebody maintains. Collectively that is a platform team’s ongoing work, and an organisation without one will not build them — which is why “do you have a platform team” is a more predictive question than any technical criterion.

  1. Count cross-component changes. Over the last quarter, how many changes touched more than one component? If it is most of them, atomicity is your dominant force. If it is almost none, the repository boundary is not costing you anything.

  2. Identify hard access requirements. Is there code some engineers must not read? Regulated material, contractor-facing work, security tooling. If yes, that code needs its own repository regardless of everything else.

  3. Check release coupling. Do components deploy independently in practice, or do they always ship together? Independent deployment favours a polyrepo; always shipping together suggests they are one thing.

  4. Measure version skew. In a polyrepo, how many versions of your main shared library are in production? If the answer is more than three, you are paying the skew cost already.

  5. Assess platform capacity. Is there a team who will own the build system, the CI scoping and the developer tooling? A monorepo without one is a bad outcome.

  6. Look at the org chart. Conway’s law applies: strongly independent teams and a monorepo produce friction; genuinely interdependent teams and a polyrepo produce coordination overhead.

  7. Decide, write it down, and set a review date. A decision record with the reasoning prevents annual re-litigation by somebody who read a conference talk.

Steps 1 and 2 do most of the work. A high cross-component change rate with no hard access requirements is a monorepo case. A low rate with a regulated component is a polyrepo case. Everything between is a judgement, and the judgement should be recorded.

The hybrid most organisations actually have

Section titled “The hybrid most organisations actually have”

Presenting this as binary is a simplification that no large organisation matches.

The common shape: one monorepo containing the components that genuinely change together, plus separate repositories for the things that must be separate — open-source projects, regulated components, contractor-facing work, and anything acquired recently.

The other common shape: a polyrepo estate with a small number of deliberate monorepos where coupling is high — a frontend monorepo, a services monorepo, an infrastructure monorepo.

Both are fine. What is not fine is arriving there without a rule. “Shared libraries and the services that consume them live in the monorepo; anything with an external audience or a read restriction lives outside it” is a rule somebody can apply. “It depends who created it” is not.

Write the rule down, in a platform README. It prevents the next fifty decisions from being made ad hoc, and it is the cheapest governance available.

Both are projects. Neither is a weekend.

Polyrepo to monorepo. Build the tooling first, decide the directory structure with the teams moving in, write CODEOWNERS before the first migration, move one willing team, learn, then move in waves. Preserve history with git subtree where anybody actually uses git log on that code. Do not migrate abandoned repositories — archive them instead. The monorepo article has the full sequence.

Monorepo to polyrepo. Extract one component at a time, starting with the most independent. History extraction is possible with filter tooling and is often not worth it. The hard part is not the code — it is replacing the atomicity you had: shared libraries must become published packages with versions, and the first six months of that are unpleasant.

In both directions: do not change behaviour during the move. A migration that is a no-op is verifiable; one mixed with functional changes is not.

And in both directions: the references are the long tail. CI configuration, documentation, deploy scripts, bookmarks, runbooks and the onboarding guide nobody has opened in a year.

Reassuring, and worth stating so the decision stays in proportion.

Your architecture. Repository structure and service boundaries are independent. A monorepo can contain forty independently deployed services; a polyrepo can contain a distributed monolith. Anybody claiming a repository layout determines your architecture is confusing two things.

Your deployment model. Components deploy independently in both, with different conventions for identifying what shipped.

Your branching strategy. Trunk-based development works in both. Long-lived branches are a bad idea in both.

Your review culture. A team that reviews carefully does so in either; a team that rubber-stamps does too. CODEOWNERS routes reviewers in both.

Your security posture. Beyond the read-access point, the controls are the same: rulesets, required review, scanning, signed commits.

Whether your CI is good. A monorepo needs path awareness sooner. Both need caching, both need reliable tests, and neither structure rescues a bad pipeline.

How much of the decision this leaves: less than the discussion around it suggests. Repository structure is one architectural choice among many, and teams that agonise over it for a quarter are usually deferring harder decisions about coupling and ownership that the structure will not settle either way.

The right structure at twelve engineers is not the right structure at twelve hundred, and the transition is gradual enough to miss.

Under about twenty engineers. One repository, whatever the architecture. Coordination is free at this size and tooling investment is not available. Splitting early is the more common mistake.

Twenty to a hundred. The first real decision point. Cross-component change rate becomes measurable, ownership starts needing to be explicit, and CI cost becomes noticeable. Most organisations here should still default to fewer repositories and add CODEOWNERS.

A hundred to a thousand. Both models need investment. A monorepo needs the full apparatus; a polyrepo needs fleet management, inventory and dependency campaigns. The cost is comparable; the shape differs.

Above a thousand. The choice is largely made by history, and changing it is a multi-year programme. Most organisations at this scale are hybrid whether or not they planned to be.

The number that predicts pain is not engineers or repositories. It is how many people must coordinate for a routine change — and when that exceeds about three, something structural is wrong in whichever model you have chosen.

Copying a large company’s structure. Their constraints are not yours, and their tooling investment is not available to you.

Splitting to fix slow clones. Almost always the wrong remedy for a Git-performance problem.

Merging to fix dependency pain. Sometimes right; frequently a symptom of over-coupled services.

Adopting a monorepo with no platform team. The costs without the machinery.

Assuming a monorepo produces code sharing. It removes a barrier; it does not create the behaviour.

Ignoring read-access requirements. There is no path-level read control, and designing around its absence is harder than a separate repository.

Not pricing version skew. The polyrepo cost that accumulates invisibly until a vulnerability makes it visible.

Treating the decision as permanent. Estates change; revisit annually.

Changing structure and behaviour together. Nothing is verifiable.

The dimension engineers actually feel daily, and it appears in no comparison table.

In a monorepo, day one is easy. One clone, one setup script, everything on disk. A new engineer can read any code they are curious about, and grep finds it.

In a monorepo, day one is also slow. The clone is the largest repository the organisation has, and without partial clone and sparse checkout configured for them, a new engineer waits.

In a polyrepo, day one is a scavenger hunt. Which repositories do I need? Six, and nobody wrote them down. Each has its own setup, its own conventions and its own README of varying quality.

Daily work differs too. A monorepo means every git status walks a large tree unless sparse checkout is configured, and every branch name competes in a shared namespace. A polyrepo means context switching between repositories, keeping several checked out, and a mental map of which one contains what.

Debugging across components is where the gap is widest. In a monorepo, stepping from a service into the shared library it calls is opening a file. In a polyrepo, it is finding the repository, cloning it, checking out the version that is actually deployed, and hoping the source matches.

Neither is uniformly better and the difference is real. If you are choosing, ask engineers who have worked in both — their answers will be strongly shaped by how much tooling each organisation had, which is itself the most useful thing the answer tells you.

An angle the technical comparison misses and enterprise readers care about.

A monorepo centralises governance and makes it coarse. One repository means one set of rulesets, one required-check configuration and one bypass list — applying to everybody’s code. That is efficient to administer and it means a control appropriate for one team is imposed on all of them.

A polyrepo distributes governance and makes it inconsistent. Each repository can have exactly the right controls, and most will not have them, because nobody applied them. This is the fleet drift problem, and it is why organisation-level rulesets and custom properties exist.

Which is easier to secure depends on your starting point. Bringing one monorepo to a standard is one configuration change. Bringing nine hundred repositories to the same standard is a programme — which the governance and fleet clusters are largely about.

Which is easier to audit is the monorepo, unambiguously. “Show that only authorised people could change production code” is one repository’s settings and one CODEOWNERS file, versus an inventory query across an estate.

Where the polyrepo wins on governance is granularity: a repository that needs stricter controls can have them without imposing them on everybody, and read access can genuinely be restricted.

The practical upshot for an enterprise: a monorepo shifts governance work from breadth to depth. There is less to configure and more riding on getting it right, because there is no repository boundary to contain a mistake.

A repository boundary buys you access control, CI scoping and release independence, and costs you atomicity and consistency. Choose based on which of those your organisation actually needs, and be honest about whether you will build the tooling that the alternative requires.

The two questions that decide most cases: how often do changes cross component boundaries, and is there code some people must not read? The first favours a monorepo as it rises; the second requires a repository boundary regardless of anything else.

  • Atomicity is the strongest argument for a monorepo; read-access control is the strongest against and has no workaround
  • Cross-component change rate and hard access requirements decide most cases
  • A monorepo does not produce code sharing; it removes a barrier to it
  • Repository boundaries do not enforce architectural boundaries
  • Version skew is the polyrepo cost that accumulates invisibly
  • Tooling investment is the monorepo cost, and it requires a platform team to own it
  • Most organisations end up hybrid, and should write down the rule for what goes where
  • Slow clones are almost never a reason to split a repository

Use your own organisation, or a hypothetical one.

  1. Take the last thirty merged pull requests. How many touched more than one component? Write down the fraction.

  2. List any code that some engineers must not read. Contractors, regulated material, security tooling.

  3. For your main shared library, count how many versions are in production across consumers.

  4. Count how many people must approve a routine cross-component change today.

  5. Name the team that would own a monorepo’s build system and CI scoping. If you cannot, that is the finding.

  6. Write the decision you would make and the two facts that decided it.

  7. Write down what would make you revisit it.

Engineering Team Onboarding SystemA 30-day Git and GitHub programme with standards templates, assessments and governance checklists.