Monorepo or Polyrepo for a Small Team, and What Nobody Tells You
The decision that's oversold on Twitter and undersold in practice. Which structure actually fits a two-to-ten-engineer startup.
A monorepo used to be an idea worth blogging about. Now it's an ideology, with all the noise that comes with one. The truth for a small team is duller: both structures work, both have costs, and the choice matters less than the discipline you apply after it.
This is the version of the conversation we have when a two-to-five-engineer startup asks whether to put everything in one repo or split it up. No dogma. Just what tends to work at that scale.
What the debate is really about
A monorepo puts all your code — frontend, backend, mobile, shared libraries, infrastructure — in one repository. A polyrepo puts each service or product in its own.
The debate isn't really about repositories. It's about coupling. Monorepos make it easier to share code and change things atomically. Polyrepos make it easier to isolate teams and deploy independently. Everything else is downstream of those two.
When a monorepo helps a small team
For most startups with two to five engineers, a monorepo is the right default. The value is concrete and immediate.
Sharing code without publishing packages
If your frontend and backend share types — which they should, if you're using TypeScript — a monorepo lets you import them directly. In a polyrepo, you're either duplicating types, publishing an internal npm package, or hand-syncing files. All three are worse than a shared folder.
Atomic changes across services
When a change touches frontend, backend, and a shared library, a monorepo lets you make one commit that updates all three. In a polyrepo, you coordinate three PRs across three repos, and there's always a moment when one is deployed and the others aren't.
One place to look
New engineers ramp faster when the whole codebase is in one place. "Where's the code for X" has one answer. "Search the codebase for Y" works.
Simpler tooling
One CI configuration. One linting setup. One version of TypeScript. This sounds small until you've spent an afternoon reconciling seven repos with slightly different tsconfigs.
When a polyrepo is the better fit
Polyrepos aren't wrong. They fit specific situations.
Independent deployment cadence
If your mobile app ships to the App Store every two weeks and your web app ships hourly, keeping them in different repos avoids weird cross-contamination in CI. The cadences never fight each other.
Different technology per service
If your backend is Python, your frontend is TypeScript, and your data pipeline is Rust, a monorepo is fighting your tooling instead of helping. Each has its own build system, its own linter, its own conventions.
Contractor or open-source scoping
If you bring in a contractor to work on one service, giving them access to a monorepo means giving them access to everything. A polyrepo lets you scope access naturally.
Same logic applies if any part of your codebase is going to be open-sourced.
The tooling reality
Monorepos have a reputation for needing heavy tooling. Turborepo, Nx, Bazel, pnpm workspaces. The reputation is half true.
For a small team, pnpm workspaces plus Turborepo is enough. Set up in an hour, works well up to about 20 engineers. You get incremental builds, task caching, and clean dependency management without the operational overhead of Nx or Bazel.
The heavier tools — Nx and especially Bazel — are worth it when you have dozens of packages, complex build dependencies, or teams that want to enforce boundaries between modules. Most startups don't need them and shouldn't adopt them until they clearly do.
The trade-offs that show up in practice
Every structure has failure modes. Here's what actually happens.
Monorepo failure modes
CI times grow. A change in one service can trigger tests across the whole repo unless you configure task graphs carefully. Turborepo helps a lot; without it, you're doing full builds you don't need.
Coupling creeps in. When it's easy to import from any folder, engineers do. The clean separation between services blurs until refactoring one requires touching three. This is fixable with lint rules that enforce module boundaries — Nx has this built in, Turborepo doesn't.
Contributor onboarding requires more context. A new engineer sees a 50k-line codebase on day one, even if they only need to work on 5k lines of it.
Polyrepo failure modes
Type drift. Frontend and backend get out of sync because there's no compiler forcing them to agree. Bug fixes ship to one repo and not the others. Version pinning gets messy.
Coordination overhead. Every cross-cutting change requires PRs in multiple places, in the right order, deployed at the right time. Miss one and you have a bug that only shows up in production.
Search fragmentation. "Which repo has the payment code" is a real question in a polyrepo, and the answer isn't always obvious.
The middle path most teams end up on
The setup that works for most startups we work with: a monorepo containing the main product (frontend, backend, shared libraries) plus separate repos for things that genuinely stand alone — a marketing site, infrastructure code, a public SDK.
This gives you monorepo benefits where they matter and polyrepo isolation where it matters. It also matches how the code actually gets used. The marketing site doesn't need to share types with the API.
Common misconceptions
"You need Google-scale tooling for a monorepo." You don't. Small monorepos work fine with pnpm workspaces and Turborepo, both of which are free and take under a day to set up. Bazel is overkill until you're a much bigger company.
"Microservices need polyrepos." They don't. You can absolutely have five services in one monorepo, each with its own deployment. The repo boundary and the deployment boundary are separate concerns.
"Monorepos scale badly." The largest codebases in the world are monorepos. What scales badly is a monorepo without discipline about module boundaries, CI performance, and code ownership.
How to migrate later, if you have to
The good news: it's cheaper to move from a monorepo to polyrepos than the reverse. Extracting a service into its own repo is a mechanical migration. Merging three repos into one requires reconciling their tooling, their conventions, and their tests.
Practical implication: start with a monorepo. If you eventually need to peel a service off, you can. Starting polyrepo and consolidating later is a much harder project.
What we usually recommend
For a startup with two to ten engineers building a web-based SaaS, a monorepo with pnpm workspaces and Turborepo is the default we suggest. It matches how the product is built, keeps types in sync, and doesn't lock you into heavy tooling before you need it.
The exception is when the team has genuine polyrepo needs — different technology stacks, radically different deployment cadences, external contributors — in which case a polyrepo or a hybrid is fine. There's no wrong answer that a disciplined team can't ship past.
Frequently asked questions
Final word
Nobody's going to lose a customer over monorepo vs polyrepo. What kills teams is switching structures under pressure, or picking one for ideological reasons and never revisiting. Pick the one that fits your team today, invest in the boring tooling that makes it work, and revisit once a year.
If you're structuring a new codebase and want a second opinion on the setup before committing, book a call. We'll walk through your product and team shape and tell you what we'd do.
FAQ
Frequently asked questions
Should a small startup use a monorepo or polyrepo?+
For most startups with two to ten engineers building a web-based product, a monorepo is the better default. It keeps types in sync, allows atomic cross-service changes, and simplifies tooling. Polyrepos fit better when technology stacks diverge sharply or deployment cadences are very different.
Do I need Nx or Bazel to run a monorepo?+
No. For a small team, pnpm workspaces plus Turborepo is enough. It gives you incremental builds, task caching, and clean dependency management without the operational overhead of heavier tools. Move to Nx or Bazel only when you have specific pain those tools solve.
Can I have microservices in a monorepo?+
Yes. Repository boundaries and deployment boundaries are separate concerns. You can absolutely have five independently-deployed services in one repository, each with its own container and its own CI pipeline. Many production systems run exactly that way.
What's the biggest downside of a monorepo?+
Coupling creeps in over time because it's easy to import from anywhere. Left unchecked, the clean separation between services blurs and refactoring becomes harder. Lint rules that enforce module boundaries prevent most of this, but they require discipline to keep in place.
Is it hard to migrate from a monorepo to a polyrepo?+
Easier than the reverse. Extracting a service into its own repository is mostly mechanical. Merging three separate repositories into one requires reconciling different tooling, conventions, and CI. Starting monorepo and splitting later is far cheaper than starting polyrepo and consolidating.
Building something similar?
Let's talk in 30 minutes.

