Byte Bound Report
Dev Tools

What Is a Monorepo? A Developer's Explainer & When to Use One

What Is a Monorepo? A Developer's Explainer & When to Use One

If you've worked across a few engineering teams, you've probably heard someone argue passionately for—or against—putting everything in one repository. The "monorepo" has become one of those architecture decisions that sparks strong opinions. Here's a practical breakdown of what a monorepo actually is, what it buys you, what it costs, and how to decide whether it fits your team.

The Basic Definition

The term is a shortening of "monolithic repository." A monorepo is a code management approach where all code for several projects is stored in a single repository. That's the whole idea: instead of scattering your web app, mobile client, backend services, and shared libraries across many separate repos, you keep them together in one version-controlled tree.

A critical clarification, because people mix these up constantly: a monorepo is not the same thing as a monolith. A monolith is an application architecture—one large, tightly coupled deployable unit. A monorepo is a source-control strategy. You can absolutely store dozens of independently deployable microservices inside a single monorepo. The two concepts operate at different layers.

Monorepo vs. Polyrepo

The alternative to a monorepo is the "polyrepo" (or "multi-repo") model, where each project, service, or library lives in its own repository with its own history, permissions, and release cycle.

The polyrepo approach feels natural. Each team owns its repo, boundaries are enforced by default, and a new service just means a new repo. The downside shows up when code needs to move between those repos: sharing a library means publishing and versioning a package, coordinating a change across three services means three pull requests in three repos, and keeping dependencies aligned becomes a manual chore.

A monorepo inverts those trade-offs. Sharing becomes trivial because everything is already in one place, but you take on the burden of managing a large, busy tree that many teams touch at once.

Why Teams Adopt Monorepos

The clearest case for monorepos comes from Google, which has run one for well over a decade and documented the reasoning publicly. The benefits it cites include unified versioning, extensive code sharing, simplified dependency management, atomic changes, large-scale refactoring, collaboration across teams, flexible code ownership, and code visibility.

A few of those deserve unpacking:

Atomic changes across projects. In a polyrepo world, changing a shared API and every consumer of it requires coordinated commits across repositories, and there's always a window where things are half-updated. In a monorepo, a single commit can update the library and every caller at once. One change, one review, one consistent state.

Easier code sharing and reuse. Because everything already lives together, there's no publish-and-consume dance to share code. This is one of the headline benefits: key benefits include simplified dependency management, easier code sharing and reuse, and streamlined tooling.

Large-scale refactoring and visibility. When every consumer of a function is in the same tree, you can find them, change them, and verify them together. Developers can also read code across the whole organization instead of hunting for the right repo and requesting access.

Google's experience is the standard proof-of-scale for the model. Google has shown the monolithic model of source code management can scale to a repository of one billion files, 35 million commits, and tens of thousands of developers. Its monolithic repository is used by 95% of its software developers worldwide, contains roughly 86TB of data, and includes approximately two billion lines of code in nine million unique source files.

That's the aspirational ceiling, not a typical target. But it demonstrates the model doesn't inherently fall apart as you grow—provided you invest in the tooling to support it.

The Trade-Offs You're Signing Up For

Monorepos are not free. The costs are real, and they show up as your tree and your team grow.

The most cited problem is that off-the-shelf version control wasn't designed for one enormous, constantly changing repository. Git tracks the state of the whole tree in every single commit, which is fine for single or related projects but becomes unwieldy for a repository containing many unrelated projects. The practical effect is friction: because the branch tip is changing all the time, frequent merging or rebasing locally is required to push changes.

Common tooling conventions also start to break down. Consider tagging: in Git a tag is a named alias for a particular commit referring to the whole tree, but its usefulness diminishes in a monorepo—if you're working on a continuously deployed web app, the release tag for a versioned iOS client is irrelevant to you. Beyond these conceptual issues, there are numerous performance issues that can affect a monorepo setup once many unrelated projects live in one place.

Other trade-offs to plan for:

  • Slow operations at scale. Clones, checkouts, and status checks get heavier as history and file count grow. Large teams end up reaching for partial clones, sparse checkouts, and other techniques to stay fast.
  • Build and CI complexity. Naively rebuilding and retesting the entire tree on every change is wasteful. You need tooling that understands the dependency graph and only rebuilds what actually changed.
  • Access control. A single repo makes fine-grained, per-project permissions harder than the natural boundaries a polyrepo gives you.

Tooling Matters More Than the Decision Itself

A monorepo only works well if your tooling is built for it. The core requirement is a system that understands which projects depend on which, so that builds and tests run only against the code affected by a change—and cache the rest.

This is a mature space. Widely used options in the JavaScript and TypeScript world include Nx, Turborepo, and Lerna, while Bazel (Google's open-sourced build system) targets large, polyglot codebases. If you're evaluating them, the practical questions are the same regardless of ecosystem: Does it model your dependency graph? Can it skip work that hasn't changed? Does it support remote caching so your CI and your teammates aren't redoing each other's builds? It's worth aligning this with your broader pipeline—our roundup of the best CI/CD tools for small teams is a useful companion here.

Without this layer, a growing monorepo will get slow and frustrating fast. With it, the model scales. You can find more guides like this in our Dev Tools section.

When to Use One—and When Not To

Reach for a monorepo when:

  • Your projects share a lot of code, or you frequently make changes that span multiple projects at once.
  • You want one consistent set of dependency versions, linting rules, and build conventions across teams.
  • You're willing to invest in build and CI tooling that understands your dependency graph.
  • Tight cross-team collaboration and code visibility are more valuable to you than hard repo-level boundaries.

Stick with separate repos when:

  • Your projects are genuinely independent, rarely share code, and ship on their own schedules.
  • You need strict, repo-level access control between teams or external contributors.
  • You don't have the appetite to maintain specialized monorepo tooling, and your current multi-repo setup isn't causing pain.

The Bottom Line

A monorepo is a strategy for where your code lives, not how your application is built. It trades the natural isolation of separate repositories for effortless code sharing, atomic cross-project changes, and a single source of truth. That trade pays off when your projects are interdependent and you're ready to invest in tooling that keeps builds and version control fast at scale. If your projects are truly separate—or you don't want to maintain that tooling—a polyrepo may serve you better. The right answer depends on how tangled your projects are and how much they need to change together.