The short answer
Pick the repository shape that matches how your code changes together. If one feature edit touches a web app, a shared package and a deployable API, a monorepo removes the version dance. If separate teams ship separate products on their own schedules, many repositories keep access and releases simpler. The tool is not the deciding factor. Code coupling is.
A growing team feels the choice in review and release work. A monorepo gives one place to review a cross-cutting change. Many repositories give each team a smaller surface to own. Both can work at scale. Both fail when boundaries are vague and nobody owns the shared pieces.
Start by mapping deployables, shared libraries and who needs read access. Then pick a default and write down the exceptions. A team can keep a monorepo for the core product and separate repositories for contractors or one-off tools. Mixed setups are common. The mistake is letting the layout grow by accident.
| Aspect | Monorepo | Many repositories |
|---|---|---|
| Code sharing | Shared packages live in the same repo, so one pull request updates the library and its callers. | Shared packages are published to a registry or consumed by tag, and each consumer bumps the version. |
| Cross-cutting change | One commit and one CI run cover the app, API and shared code. | Several pull requests need an order, a compatibility window and a rollout plan. |
| Access control | Read access is repo-wide; folder permissions are not a security boundary in plain Git. | Each repo has its own permissions, so contractors or separate teams see only what they need. |
| CI and build time | Needs affected builds, path filters and remote cache to avoid running every job. | Each repo runs its own pipeline; shared templates keep checks consistent. |
| Versioning and releases | One lockfile or version policy aligns dependencies, and apps can still deploy separately. | Independent versions and tags, plus a compatibility matrix for consumers. |
| Ownership | CODEOWNERS and folder rules define owners inside one repository. | Repository ownership is explicit, and a service catalog helps people find the right repo. |
| Onboarding | One clone gives all code, which is useful for search and can overwhelm new engineers. | People clone only what they need, but discovery depends on docs and naming. |
| Repository sprawl | One large repo can become a dumping ground without boundary rules. | Many repos need templates, archive rules and an index to stay manageable. |
How a monorepo works
A monorepo puts several apps, services and shared packages under one Git history. The root holds workspace config and tooling. Packages live in folders such as apps/web, services/billing and packages/ui. Tools like pnpm workspaces, Nx, Turborepo, Bazel, Gradle or Cargo workspaces define the project graph, so a build can run only what changed. A CI job can use path filters or an affected command to skip untouched projects. Remote caching makes repeat builds cheaper.
The main gain is atomic change. One pull request updates a library and every caller, and CI tests the whole graph. Reviewers see the blast radius in one diff. Dependency versions can be aligned through one lockfile or one version policy. Refactoring shared code is direct because there is no publish step between the caller and the library.
The main cost is coordination. Git grants read access at the repository level, so folder permissions are not a real security boundary in a plain monorepo. Everyone with clone rights can read all code. Build times grow unless you invest in caching and project graph tools. CI can fan out into many jobs from one push. Without CODEOWNERS and clear folder rules, the repo turns into a shared dumping ground.
How many repositories works
Many repositories give each app, service or library its own Git history. A team can grant write access to one repo and keep another closed. Releases are independent: tag version 2.4 of the billing service and deploy it without touching the web app. CI config lives with the code it builds, so a pipeline change affects one project. Repository templates keep the setup consistent as new projects appear.
The hard part is the seams. A change that spans the web app and the API becomes several pull requests. You need an order, a compatibility window and a way to roll out the API before the client. Shared libraries must be published to a package registry or consumed by Git tag, and each consumer needs a version bump. Dependency update tools such as Dependabot or Renovate help, but someone still owns the policy.
Many repositories also need a map. New engineers have to find the right repo, read its README and learn its release process. A service catalog or a short index in the org README fixes most of that. Cross-repo search is weaker than in a monorepo, so naming and docs matter more. Repository sprawl is real. Archive dead repos and set a template for new ones.
When to choose a monorepo
Choose a monorepo when the code changes together. A product with a web app, mobile app, API and shared type definitions is a strong fit. So is a platform team that maintains common libraries for several internal services. Atomic refactors, one CI policy and one place to search code save real time. You can still deploy each app separately. A monorepo is a code layout, not a deployment unit.
It also fits teams that want a single review culture. One pull request can show a schema change, the generated client and the caller update. That is easier to reason about than three linked PRs in three repos. If your engineers already use a build tool with a project graph, the path is shorter.
Skip a monorepo when access must be segmented by regulation, customer or contract, and folder permissions are not enough. Skip it when products have unrelated release cycles and almost no shared code. Skip it when nobody will own the build tooling. A monorepo without cache and affected builds becomes slow, and slow CI teaches people to batch changes.
When to choose many repositories
Choose many repositories when team ownership is clear and releases are independent. Different products, different customers or different compliance scopes often need separate access. A contractor working on one integration should not get the core platform. A small service with one maintainer is easier to run in its own repo. Independent versioning also helps when consumers upgrade on their own schedule.
Many repositories work best with strong contracts. Publish APIs with OpenAPI or protobuf, version packages with semantic versioning, and test against the published artifact, not a local path. Keep a shared CI template so each repo gets the same checks. A manifest repo or a small deployment repo can pin versions for an environment without merging all code.
This model needs discipline as the team grows. Every new repo adds a README, an owner, a release process and a dependency policy. Without that, you get a maze of similar names and stale projects. The payoff is a small blast radius. A broken build in one repo does not block every team. That matters when teams ship on different clocks.
Costs and effort to consider
Both models carry a tooling bill. A monorepo needs a project graph, affected builds, remote cache, merge queue and CODEOWNERS. You also need a policy for shared dependency versions and a way to keep CI from running every job on every push. Many repositories need templates, a package registry, cross-repo dependency updates and a service catalog. Neither model removes the need for an owner. The work moves, it does not vanish.
Estimate the people cost before the tool cost. Who will maintain the build config? Who reviews shared library changes? Who handles access requests? A monorepo often needs one platform-minded engineer to keep the graph healthy. Many repositories spread that work across teams, but each team now runs its own release process. Pick the model that matches the skills you have, not the one that looks neat in a diagram.
Migration is the other cost. Splitting a repo means rewriting CI, changing import paths and teaching people new habits. Merging repos means preserving history and untangling access. Do it in slices, keep the old path working until the new one is stable, and document the boundary rules. If the repo plan is clear and the release plumbing is not, Cloudverg's Delivery platform setup at $14,500 fixed price is one option among others: four weeks to stand up pipelines, environments, secrets, monitoring and rollback. An internal platform hire or a smaller scripted setup can also fit.
Frequently asked questions
Is a monorepo better than many repositories?
Neither is better by default. A monorepo fits code that changes together. Many repositories fit separate teams with separate access and release cycles. Pick based on coupling and ownership, not fashion.
Can a monorepo hold more than one language?
Yes. Tools such as Bazel, Nx or Gradle support mixed stacks, and you can also keep simple path-based scripts. The work is in the project graph and CI, not in the Git layout. A monorepo does not force one language or one runtime.
Does a monorepo mean one deployment?
No. A monorepo is a code layout. Each app or service can have its own pipeline, environment and release cadence. The repo shape changes how you review and build code, not how you deploy it.