Codebase organisation comparison

Monorepo vs polyrepo

One repository for everything, or one repository per project? The answer drives how teams coordinate, how CI scales, and how easy cross-project changes feel.

TL;DR

  • Monorepo — one Git repository contains many projects. Atomic cross-project commits, shared tooling, single version of truth — at the cost of CI infrastructure investment.
  • Polyrepo — each project owns its repo. Smaller, focused, simpler — at the cost of dependency drift and harder cross-cutting changes.
  • The right choice tracks team coupling. Tightly-coupled teams → monorepo. Loosely-coupled, independent teams → polyrepo.

Side-by-side comparison

AspectMonorepoPolyrepo
RepositoriesOneMany
Cross-project changeOne PR atomic across servicesMultiple PRs coordinated; release ordering matters
Dependency versioningOne version of everythingEach repo pins its own versions — drift inevitable
Code sharingTrivial — import directlyVia published packages with semver
CI scopeMust compute affected projects to stay fastNaturally scoped per repo
ToolingNx, Turborepo, Bazel, Pants required at scaleStandard Git + per-repo CI is enough
DiscoveryOne search across everythingPer-repo search; cross-repo discovery is hard
Access controlPath-based or trust-basedPer-repo, GitHub/GitLab native
CloningSlow as repo grows (shallow / sparse helps)Fast — only what you need
Used byGoogle, Meta, Microsoft, Uber, XMost open-source, most startups

Layout side-by-side

Monorepo

acme/                  ← single repo
  apps/
    web/
    mobile/
    admin/
  services/
    auth/
    billing/
    orders/
  packages/
    ui/                ← shared UI lib
    config/
    types/
  package.json         ← root workspace
  turbo.json           ← build orchestration
  .github/workflows/

Polyrepo

acme/web                ← separate repo
acme/mobile             ← separate repo
acme/admin              ← separate repo
acme/auth-service       ← separate repo
acme/billing-service    ← separate repo
acme/orders-service     ← separate repo
acme/ui-library         ← published as @acme/ui
acme/types              ← published as @acme/types

# Each repo:
#   package.json with deps on @acme/ui@^1.2
#   its own CI, releases, README

When to choose a monorepo

  • Shared design system / types. Frontend, mobile-web, and admin tools sharing a UI library — atomic upgrades are huge.
  • Tightly coupled services. Updating an API contract and all its consumers should be one reviewable change.
  • Standardised tooling. One linter config, one CI template, one dependency upgrade strategy across many projects.
  • Single-org refactoring. "Rename this function everywhere" should be one PR, not 23.
  • You have engineers to invest in CI tooling. Nx/Turborepo/Bazel are not free to set up and maintain.

When to choose polyrepos

  • Independent teams with independent products. No reason to couple their release cycles.
  • Open-source projects. External contributors expect focused, well-scoped repos.
  • Strong service boundaries already. No frequent cross-service changes — coordination overhead is rare.
  • Limited platform team. No one to own monorepo tooling; standard GitHub workflow is fine.
  • Compliance separation. Some code must be visible only to specific teams; per-repo ACLs are simpler than path-based.

English phrases engineers use

Monorepo conversations

  • "This PR updates the shared types and all consumers in one change."
  • "CI is rebuilding everything — we need affected-project detection."
  • "Codeowners for the auth package — review required from the auth team."
  • "Use workspaces for the package linking, not symlinks."
  • "Sparse checkout — junior devs don't need the entire codebase."

Polyrepo conversations

  • "We need to release the library first, then bump it in the consumer."
  • "This is dependency drift — three services on three different SDK versions."
  • "The change spans four PRs across four repos — let's coordinate the merge order."
  • "Renovate bot is keeping all repos on the latest minor."
  • "Open a cross-repo issue — link them so we don't lose track."

Quick decision tree

  • Frontend + design system shared across products → Monorepo
  • Microservices with frequent cross-service API changes → Monorepo (with tooling)
  • Open-source library → Polyrepo
  • Small team, single product, < 10 engineers → Either works; default monorepo for simplicity
  • Independent product teams, weekly cross-team contact → Polyrepo
  • Compliance-isolated codebase (PCI, classified) → Polyrepo
  • No platform team to maintain tooling → Polyrepo
  • You said "monorepo" and your team groaned → Polyrepo — culture matters

Frequently asked questions

What is a monorepo?

A monorepo is a single version-control repository containing the code for many projects, services, or libraries — owned by the same organisation. Google, Meta, and Microsoft famously run multi-billion-line monorepos; smaller teams use them for related microservices, design systems, or shared tooling.

What is a polyrepo?

A polyrepo (or "multi-repo") setup gives each project its own version-control repository. This is the default model on GitHub and the historical norm — each service, library, or product lives in a separate repo with its own issues, releases, and access control.

Are monorepos faster to work in?

For atomic cross-project changes, yes — you can update an API and all its consumers in one PR. For everyday work in a single project, polyrepos are usually faster (smaller repo to clone, faster CI, less context to learn).

Do I need special tooling for a monorepo?

For more than a handful of projects, yes. Build systems like Nx, Turborepo, Bazel, or Pants compute affected projects per PR so CI does not rebuild the world on every commit. Without that tooling, monorepo CI becomes extremely slow.

What is a "trunk-based development" monorepo?

A monorepo where everyone commits to a single main branch (no long-lived feature branches), backed by feature flags and CI gates. This is the dominant pattern at Google and similar large companies — it scales well when paired with strong test culture and code review.

Can I have a hybrid?

Yes — many teams keep tightly-coupled code (e.g. frontend monorepo with web, mobile-web, and design system) in one repo, while keeping unrelated backend services in their own repos. The grouping should follow team boundaries and change-frequency, not arbitrary technical lines.

What is the most underrated cost of polyrepos?

Dependency drift. The shared library is v1.4 in repo A, v1.7 in repo B, v0.9 in repo C — and a security patch must be released to all of them. Monorepos make "one version of everything" trivial; polyrepos make it a perpetual project.