Monorepo vs Polyrepo: Pros, Cons and How to Choose
Monorepos and polyrepos compared: code sharing, atomic changes, CI speed, ownership, tooling and the team sizes where each one works best.
· 6 min read
Contents
- Definitions
- Side-by-side comparison
- Advantages of a monorepo
- Atomic changes
- Easy code sharing
- Consistent tooling
- Visibility
- Disadvantages of a monorepo
- CI can get slow
- Coarser permissions
- Scale problems
- Tight coupling risk
- Advantages of a polyrepo
- Disadvantages of a polyrepo
- How to choose
- A simple monorepo layout
- CI path filters example (GitHub Actions)
- Migrating between the two
- FAQ
- Do big companies use monorepos?
- Is a monorepo slower to clone?
- Can different projects in a monorepo use different languages?
- Further reading
Should all your code live in one repository, or should every service and library get its own? Big tech companies are famous for giant monorepos, while many other organizations run hundreds of small repositories. Both approaches work — and both can go badly.
This comparison explains the real trade-offs so you can pick the structure that fits your team today.
Definitions
- Monorepo: one repository containing multiple projects — for example a web app, a mobile app, an API and shared libraries — usually with tooling that understands the boundaries between them.
- Polyrepo (or multi-repo): each project, service or library lives in its own repository, with its own history, CI and releases.
A monorepo is not the same as a monolith. A monorepo can contain dozens of independently deployed services; a monolith is a single deployable application, which can live in either structure.
Side-by-side comparison
| Monorepo | Polyrepo | |
|---|---|---|
| Code sharing | Import directly, always the latest version | Publish packages, manage versions |
| Cross-project changes | One commit / one pull request | Coordinated PRs across repos |
| Dependency versions | Easy to keep consistent | Each repo drifts independently |
| CI | Needs "affected only" builds to stay fast | Simple per repo, but duplicated config |
| Access control | Coarser (path-level rules) | Fine-grained per repository |
| Ownership | Via CODEOWNERS and folder conventions | Natural per repository |
| Tooling needs | Higher (build orchestration, caching) | Lower per repo, higher for coordination |
| Discoverability | Everything is searchable in one place | Code scattered across repos |
| Git performance at scale | Can degrade with huge histories | Not a concern |
Advantages of a monorepo
Atomic changes
Change an API and every client of it in a single pull request. Reviewers see the whole change, CI tests it together, and nothing is ever deployed half-updated. In a polyrepo the same change means publishing a new library version and opening follow-up PRs in every consumer.
Easy code sharing
Shared UI components, types, validation rules or utility functions are just folders. No private package registry, no version bumps, no "which version of the shared lib does this service use?"
Consistent tooling
One linter config, one formatter, one set of dependency versions, one CI pipeline definition. Upgrades — a new framework version, a security patch — happen once, everywhere.
Visibility
Anyone can search the whole codebase, see how an internal API is used and make fixes across team boundaries.
Disadvantages of a monorepo
CI can get slow
Running every test on every change does not scale. You need tooling that builds and tests only the projects affected by a change, plus caching. Tools such as Turborepo and Nx (JavaScript/TypeScript), Bazel and Pants (multi-language) exist for exactly this.
Coarser permissions
Most Git hosts grant access per repository. If contractors or partners should see only part of the code, a monorepo makes that harder.
Scale problems
Very large monorepos can strain Git: slow clones, slow status checks. Features such as sparse checkout, partial clone and file-system monitors help, but at extreme sizes companies build custom tooling.
Tight coupling risk
Because it is easy to import anything, projects can become entangled. Clear module boundaries and lint rules that forbid certain imports keep things sane.
Advantages of a polyrepo
- Clear ownership and autonomy: each team controls its repository, CI, release schedule and tools.
- Simple, fast CI per repository: the pipeline only ever builds one thing.
- Fine-grained access control: share exactly the repositories each person needs.
- Independent versioning: libraries follow semantic versioning and consumers upgrade when ready.
- Easy to open-source a single component.
Disadvantages of a polyrepo
- Cross-cutting changes are painful: coordinated PRs, release ordering, temporary compatibility code.
- Version drift: services end up on different versions of shared libraries and frameworks, and upgrades become large projects.
- Duplicated configuration: CI pipelines, linters and Dockerfiles copied and slowly diverging.
- Harder local development when a feature spans several repos that must be cloned, linked and run together.
How to choose
Pick a monorepo when:
- One team (or a few closely collaborating teams) works across frontend, backend and shared code.
- Changes often touch several projects at once.
- You want consistent tooling and dependencies with minimal overhead.
- You are a startup or small company — this is the common default, because the coordination costs of polyrepos arrive long before the scaling costs of monorepos.
Pick a polyrepo when:
- Teams are independent, with separate release cycles and little shared code.
- Strict access control between projects is required.
- Projects use very different languages and toolchains with nothing in common.
- Components are open-sourced or consumed by external parties as versioned packages.
Hybrid setups are common: a monorepo per product or domain, with truly independent systems in separate repositories.
A simple monorepo layout
my-product/
├── apps/
│ ├── web/ # Next.js frontend
│ └── api/ # FastAPI backend
├── packages/
│ ├── ui/ # shared React components
│ └── config/ # shared lint/TS config
├── .github/workflows/
├── Makefile # one command menu for everything
└── README.md
Start without heavy tooling: workspaces in your package manager (npm, pnpm or Yarn workspaces), a Makefile as the shared entry point, and CI path filters so the API pipeline only runs when apps/api/ changes. Add a build orchestrator when CI time actually becomes a problem.
CI path filters example (GitHub Actions)
on:
pull_request:
paths:
- "apps/api/**"
- "packages/config/**"
Migrating between the two
- Polyrepo → monorepo: you can preserve each repository's history by importing it into a subfolder (for example with
git filter-repo --to-subdirectory-filterfollowed by a merge with--allow-unrelated-histories). Move one repository at a time and fix CI as you go. - Monorepo → polyrepo: extract a folder with its history using
git filter-repo --subdirectory-filter, publish shared code as packages, and replace direct imports with versioned dependencies.
Either migration is a project, not an afternoon — which is a good reason to choose deliberately at the start.
FAQ
Do big companies use monorepos?
Several famous ones do, with extensive custom tooling. Many others use polyrepos or hybrids. Their choice is driven by their scale, which is rarely yours.
Is a monorepo slower to clone?
At small and medium sizes, the difference is negligible. Very large monorepos use shallow clones, partial clones and sparse checkouts to stay fast.
Can different projects in a monorepo use different languages?
Yes. A Python API and a TypeScript frontend side by side is common. Multi-language build tools help at scale; simple Makefiles or scripts are enough for small repos.
Further reading
Keep reading
SQLite vs PostgreSQL: Which Should You Use for Your Project?
An honest comparison of SQLite and PostgreSQL covering performance, concurrency, features, hosting and backups — with a simple rule for choosing.
REST vs GraphQL: Differences, Trade-offs and When to Use Each
REST and GraphQL compared with real request examples: data fetching, caching, versioning, errors, security and tooling — plus a simple rule for choosing.
FastAPI vs Flask vs Django: Which Python Framework to Choose
A practical comparison of FastAPI, Flask and Django: the same endpoint in each, performance, async, admin, ORM, learning curve and which fits your project.