If your product is young, your team is small and your apps share code, use a monorepo. If you run independent teams that release on their own schedules and rarely touch each other's code, a polyrepo fits better. The rest of this article explains why, where each approach hurts, and how to decide without turning it into a religious war.
A monorepo keeps every project in one version-control repository with one shared history. A polyrepo splits the code across many repositories, each with its own history, CI pipeline and permissions (Sourcegraph). I'm Hanad Kubat, a senior engineer who builds first real versions of software for founders and owner-operated businesses. This is the decision I make at the start of nearly every build, so I'll show you how I think about it.
Key Takeaways
- A monorepo is a storage decision, not an architecture decision. It does not force you into a monolith or into releasing everything together.
- Choose a monorepo when your apps share code (types, UI, validation) and you change them together. Choose a polyrepo when teams and release cycles are truly independent.
- Monorepos cost you build tooling and access-control coarseness. Polyrepos cost you version drift and coordinated pull requests.
- If you are unsure, start with a monorepo: splitting later is painful but possible, while merging repositories with their history intact is harder.
- The best practices are few: affected-only builds, caching, clear ownership, strong package boundaries.
Table of Contents
- What a monorepo and a polyrepo actually are
- How the two compare in daily work
- Monorepo advantages and disadvantages
- Polyrepo advantages and disadvantages
- When each one fits
- Monorepo best practices that matter
- Moving between the two later
- Perspective
- A concrete example: a small SaaS
- Working with me
- FAQ
- Sources
What a monorepo and a polyrepo actually are
A monorepo is a single repository that holds several independent projects. Frontend code, backend services, shared component libraries, infrastructure configuration and documentation can all live in one structure (Spacelift). Large companies such as Google, Facebook and Twitter are the usual examples (HackerOne).
A polyrepo is the opposite: smaller repositories, each with a narrow responsibility, its own build environment, CI pipeline and deployment process (Buildkite). Think one repository for the API, one for the web app, one for the mobile app, one for a shared library.
The central difference is where the boundary sits. A monorepo draws it around the whole system. A polyrepo draws it around every service, library or app (LogRocket).

A monorepo is not a monolith
Founders often mix these up. A monolith is a deployment decision: one process, one release artifact, one rollback. A monorepo is only about where the source lives. Sourcegraph points out that even Google's well-known paper on its repository states that a monolithic codebase does not imply monolithic software design (Sourcegraph).
Nor does a monorepo force everything to ship together. Projects build from the same commit, but each build artifact or Docker image carries its own tag, and you control when a tag reaches production. What a monorepo does force is that every project builds against the latest shared code (Nx).
How the two compare in daily work
The differences show up in five places: code sharing, dependencies, testing, releases and coordination.
| Area | Monorepo | Polyrepo |
|---|---|---|
| Shared code | Imported directly from the same repository | Published as versioned packages |
| Cross-project change | One pull request updates an API and its consumers | Several pull requests and releases |
| Dependencies | Usually one dependency file per language | Each repository has its own file, so you check across repositories |
| CI | Needs tooling to run only what changed | Separate pipelines, tuned per project |
| Access control | Shared, with per-folder ownership rules | Repository-level permissions |
| Release cadence | Any schedule, but built against latest shared code | Independent by default |
The table follows the comparison in the Nx knowledge base, and the dependency-file point comes from Endor Labs. Here is what each row means in practice.
Code sharing and atomic changes
Say you rename a field in your API. In a monorepo, the API change, the web app update and the mobile app update land in one atomic pull request (Earthly). Reviewers see the whole blast radius at once, and nothing is ever deployed half-updated on your main branch.
In a polyrepo, the same change means a pull request in the shared library, a release, then a pull request in each consumer. For a team of two or three people, that is a lot of ceremony for a field rename.
Dependency drift
In a polyrepo, dependency drift is structural, not accidental. Sourcegraph quotes Netflix's engineering team describing the risk: once a transitive dependency version changes, some code runs against a version it has never been tested with (Sourcegraph). A monorepo lets you enforce a single version policy, though the policy is optional and still takes discipline.
Testing and builds
A monorepo can build and test several projects together, but build times can grow and dependency management can get more complex. Separate repositories have pipelines optimized per project, but need more pipeline configuration and coordination (Defra Software Development Standards).
Thoughtworks also notes that monorepos make it easier to run automated unit, integration and end-to-end tests together (Thoughtworks). For a small product, that matters more than raw build speed.
Releases
If independent release cadence is a hard requirement, a polyrepo fits. If your services deploy together and your people share code daily, a monorepo fits (Sourcegraph). Versioning follows the same logic: simple projects can share one version, while components not composed into one application should be released and versioned independently (Defra).
Monorepo advantages and disadvantages
What you gain
- Atomic cross-cutting changes. One commit can touch several parts of the system (GitHub Learn).
- Code sharing without a release cycle. A shared type or validation function is just an import.
- A unified codebase that is easier to navigate and simpler dependency management for shared libraries (same GitHub source).
- Simpler collaboration. All code, pull requests, issues and release notes sit in one place (Defra).
What you pay
- Build tooling. Without dependency-aware caching, CI slows down as the repository grows. Large repositories can slow builds and CI/CD, and merge conflicts can become more frequent (GitHub Learn).
- Coarse access control. If a contractor must not see part of the code, a single repository is a poor fit. Separate repositories let you apply a unique security policy to each component (Spacelift).
- Coupled teams. A monorepo can create tightly coupled collaboration between independent teams, leading to conflicts and bottlenecks (Defra).
- Discipline. Spacelift also lists complex CI/CD configuration and dependence on developer discipline among the trade-offs.
Polyrepo advantages and disadvantages
A polyrepo gives you independent release cadence, blast-radius isolation, fine-grained access control and standard tooling. The price is coordinated cross-repository pull requests, structural dependency drift, code duplication and harder discovery (Sourcegraph).
Spacelift adds that polyrepos tend to align well with microservices, because developers can work on each service without affecting its neighbors. It also lists the downsides: deployments to coordinate across repositories, limited system-level visibility into the effects of a change, harder onboarding, and projects drifting into inconsistent standards (Spacelift).
Nx puts the cost of sharing plainly: with a polyrepo, sharing code gets harder and every maintenance task must be repeated across all repositories (Nx).
When each one fits
Ask three questions.
- Do your projects share more than configuration? Vercel's rule of thumb: if they share more than configs, a monorepo likely fits. If they're truly independent, a polyrepo might work better (Vercel Academy).
- Do you make frequent cross-project changes? If yes, atomic commits are worth a lot.
- Do teams need isolation? Strict repository-level access control, different tech stacks, or teams with different release cycles and zero coordination point to polyrepo (Vercel Academy).
Nx frames it this way: monorepos optimize for atomic changes and shared tooling, polyrepos optimize for team isolation, and with modern build tooling the technical challenges of a large repository are solvable, so the choice is mostly organizational (Nx). LogRocket calls it a trade-off between coordination and autonomy (LogRocket).
A quick decision guide
| Your situation | Likely fit |
|---|---|
| One to five engineers, web app plus API plus shared types | Monorepo |
| Web, mobile and backend sharing validation and data models | Monorepo |
| Several autonomous teams, each owning a service, rarely sharing code | Polyrepo |
| Part of the code must be hidden from some contributors | Polyrepo for that part |
| Unsure | Monorepo, split later if needed |
On the last row: Vercel advises starting with a monorepo when uncertain, because splitting is painful but possible, while merging several repositories and keeping git history can be challenging (Vercel Academy).
Monorepo best practices that matter
Most monorepo pain comes from a handful of skipped basics.
- Build and test only what changed. Use dependency-graph-based affected-project detection, caching and parallel execution instead of rebuilding everything on every change (SevyDevy). Tools such as Bazel, Nx and Turborepo exist for this (Aviator).
- Give packages strong boundaries. Deliberate public APIs, and only global settings at the repository root (monorepo.guide).
- Install dependencies where they are used. Turborepo recommends installing a dependency in the package that uses it, because explicit manifests improve clarity, caching and dependency pruning (Turborepo docs).
- Define ownership. Use CODEOWNERS, single pull requests for cross-package changes and trunk-based development. GitScrum's list of anti-patterns includes unclear ownership, circular dependencies, running all CI every time and giant pull requests (GitScrum).
- Share tooling configuration. One lint, formatting and TypeScript baseline that packages extend.
Moving between the two later
Migration is possible in both directions, but it is real work. Consolidating repositories can break existing CI/CD, create merge conflicts and require new tooling, so gradual adoption and clear ownership matter (Aviator). Moving from a monorepo to multiple repositories can cost significant time and effort (Thoughtworks).
If you consolidate a Node.js codebase, InfoQ recommends planning a short code freeze, scripting the critical migration steps to verify tools work before and after, and listing every everyday tool and workflow as acceptance criteria (InfoQ).
If you split a monorepo, move one bounded component at a time, give each code area an accountable owner, and run cross-repository CI checks before cutover (ONES). The same source makes a useful point: a directory split alone is not a boundary if teams still need coordinated releases for every change. Draw lines around ownership, release cadence and dependency direction.
Perspective
I build the first real version of a product, usually in two to four weeks, alone, and I hand it to someone else afterward. That shapes my view. For that situation I default to one repository: a Next.js app, a Node or Cloudflare Workers API, and a shared package for types and validation, all in TypeScript.
The reason is not fashion. When one person builds a product end to end, the cost of a polyrepo is pure overhead: version bumps, cross-repository pull requests, duplicated configuration. The cost of a monorepo is build tooling, and for a product this size that is a few lines of configuration.
Handover is the second reason. The next developer clones one thing, runs one install, and sees the whole system. Every founder I work with owns the code from the first commit, and a single repository makes that ownership easy to see and easy to transfer. I wrote more about that in how a monorepo helps founders ship an MVP and in what to insist on in code ownership contracts.
If your company later grows into autonomous teams with separate release cycles, splitting is a conversation worth having then. Until that day, I would not pay the polyrepo tax for a problem you do not have.
Hanad Kubat
A concrete example: a small SaaS
Picture a founder with a customer web app, an admin panel, an API and a Stripe webhook handler. All four need the same data types and the same validation rules for an order or an account.
In a monorepo, that looks like three or four app folders and one or two shared packages. Changing a validation rule is one pull request, one review and one test run covering every consumer. The deployment pipeline for each app can still be separate, and you can read more on how a deployment pipeline works.
In a polyrepo, the shared package needs its own repository, release process and version numbers. Each app pins a version, and sooner or later one of them runs an old one. For a team of fifty, that independence may be worth it. For a team of one to five, it rarely is.
The same logic applies when you inherit code. If an agency or a no-code tool left you with scattered repositories that nobody understands, consolidating them is often the first step toward a clean, documented handover.

Working with me
If you need a working first version, or a prototype from Lovable, Bolt or a similar tool rebuilt as maintainable code, I do that at a fixed price. Builds start from €12,000, with no agency overhead or project-manager layer, and you own the code from the first commit. The stack is deliberately boring and widely known so the next developer can pick it up. You can see what I build and how to start on hanadkubat.com.
FAQ
Is a monorepo better than a polyrepo?
Neither is universally better. A monorepo suits heavy code sharing and atomic cross-project changes, while polyrepos suit genuinely independent services with isolated access and release cycles (Software Engineering Guide). For a small team building one product, I would pick a monorepo.
Does a monorepo mean everything deploys at once?
No. Projects build from the same commit, but each artifact carries its own tag, and you decide when it goes to production (Nx). A monorepo only guarantees that everything builds against the latest shared code.
Do monorepos get slow as they grow?
They can, if CI rebuilds everything on every change. The usual fix is affected-project detection, caching and parallel execution (SevyDevy). Teams that skip this step are the ones who complain about slow monorepos.
Can I switch later if I choose wrong?
Yes, in both directions, but expect real effort. Splitting is painful but possible, while merging repositories with their history intact can be harder (Vercel Academy). That is why starting with a monorepo is the safer default when you are unsure.
When should I pick a polyrepo?
Pick it when strict repository-level access control is a hard requirement, or when teams share little code and nothing should force them to move together (Nx). Microservice setups with autonomous teams are the classic case.
Sources
- Sourcegraph: Monorepo vs Polyrepo
- Spacelift: Monorepo vs. Polyrepo
- HackerOne: Evaluating monorepo vs polyrepo
- Buildkite: Monorepo vs. Polyrepo
- LogRocket: Monorepos vs. Polyrepos
- Nx: Monorepo vs Polyrepo
- Earthly: Monorepo vs Polyrepo
- Endor Labs: Polyrepo vs. Monorepo and dependency management
- Defra Software Development Standards: mono repo or multi repo
- GitHub Learn: repository architecture strategy
- Thoughtworks: Monorepo vs. multi-repo
- Aviator: Monorepo hands-on guide
- Vercel Academy: Monorepos vs Polyrepos
- GitScrum: Monorepo management best practices
- Turborepo: Managing dependencies
- monorepo.guide: Thinking in monorepos
- SevyDevy: Monorepo build systems
- InfoQ: Turning a Node.js monolith into a monorepo
- ONES: Monorepo-to-multirepo migration
- Software Engineering Guide: Version control and source management
