Skip to content

A monorepo is a single repository containing multiple distinct projects, with well-defined relationships between them. The projects can be applications, libraries, or tools, and they can use the same stack or different ones. A monorepo is not a monolith: each project inside it stays separate and can be built, tested, and deployed on its own.

The "well-defined relationships" part matters. Putting many projects in one repository is easy, but without tooling that understands how they depend on each other, the repository gets slower and messier as it grows. Whether one repository or many is right for your organization is a separate decision, covered in Monorepo vs polyrepo.

  • Shared code without publishing overhead - Sharing a library is as simple as creating a folder: no versioned packages to publish and no waiting for consumers to upgrade. Reuse validation logic, UI components, and types across your entire organization, including between the backend and the frontend.

  • Single source of truth - Common code lives in one place, so every project sees what already exists instead of rebuilding it, and a bug is fixed once for every consumer.

  • Atomic changes - Change a server API and every application that consumes it in the same commit. There's no coordinating a chain of pull requests across repositories, and no window where consumers are broken.

  • Enforceable conventions at scale - Lint rules, code style, and dependency policy apply everywhere automatically, so consistency is the default instead of a per-repository chore.

  • Developer mobility - Build and test every project the same way, regardless of the tools it uses. Developers can contribute to another team's application and verify their changes are safe without learning a new setup.

  • Single set of dependencies - Keep every project on the same version of each third-party dependency. The policy is optional, but a monorepo is the only place you can enforce it. Less actively developed applications still get framework and tooling updates instead of falling years behind.

No. A monolith is a single application that ships as one deployable unit. A monorepo is a version-control strategy: one repository holding many projects that are built, tested, and deployed independently. Teams often adopt a monorepo specifically to break a monolith into smaller projects while keeping all the code in one place.

Some of the largest codebases in the world are monorepos:

  • Google keeps most of its code in one repository, described in the 2016 ACM paper "Why Google Stores Billions of Lines of Code in a Single Repository."
  • Meta develops its main products in a monorepo and built the Sapling version control system to keep it fast at that scale.
  • Microsoft hosts the Windows codebase in one of the largest Git repositories in existence and built dedicated tooling (VFS for Git, later Scalar) to keep cloning and fetching it practical.

You don't need to be at that scale to benefit: shared code, atomic changes, and one set of dependencies apply just as well to a repository with five projects.

A naive implementation of a monorepo is code collocation: combining the code from multiple repositories into one without adding any tooling. Large companies that use monorepos don't just put all the code in one place, and without tooling to coordinate everything, problems arise as the repository grows:

  • Running unnecessary tests - CI runs every test in the repository on every change to make sure nothing breaks, including tests for projects the change can't possibly affect.

  • No code boundaries - Any team can change or depend on any code, including code you intended to keep private. Once another project depends on your internals, you can't change them without breaking that project.

  • Inconsistent tooling - Each project keeps its own commands for testing, building, serving, and linting. Every project switch means relearning how to run things.

Package manager workspaces (npm, pnpm, Yarn, and Bun) solve a different problem: they install and link local packages so projects can import each other. They don't build a task graph, cache results, or detect which projects a change affects. Lerna adds versioning and publishing on top, and modern Lerna delegates task running to Nx.

Why do AI coding agents work better in monorepos?

Section titled “Why do AI coding agents work better in monorepos?”

AI coding agents get more from a monorepo than from scattered repositories:

  • Full context - Agents read the actual source of every project they touch and navigate directly between the frontend, backend, and libraries, instead of guessing against out-of-date API specs in other repositories.

  • A queryable project graph - Tooling exposes which projects exist, how they relate, and what tasks run, so agents don't burn tokens exploring the repository.

  • Tight feedback loops - Affected-only task runs and caching verify every agent change quickly.

  • Guardrails - Module boundary rules keep agent-written code inside your architecture, and generators produce consistent, convention-matching scaffolding.

  • CI that keeps up - As agents raise PR volume, distributed task execution and self-healing CI keep the pipeline from becoming the bottleneck.

To learn how Nx gives agents this context and these guardrails, see Enhance your AI coding agent. To configure your Nx workspace for AI agents, see AI setup.

Without graph-aware tooling, a monorepo makes CI slower, not faster, because every pipeline runs every task. Nx adds the layer that solves those collocation problems and keeps the repository fast as it grows: