How to choose between a monorepo and multiple repos

Every team that starts a second service asks the same question: does this new code go in the same repository as the first one, or does it get its own? The question sounds like a style preference. It is not. It decides how your team reviews code, how it deploys, and how fast a change can move from one part of the system to another for the rest of the project's life.
We have watched teams pick a repository structure because a conference talk from a big company recommended it, then spend a year working around the mismatch between that structure and their actual size. The right choice is not about which pattern is more modern. It is about three measurable things: how many people are touching the code, how tightly your services have to deploy together, and how often code needs to move between them. A fourth factor has become real in the last two years: what an AI coding agent can and cannot see across a repository boundary.
Start with team size, not architecture
The instinct is to pick a repository shape based on how the system is designed: microservices go in separate repos, a single application goes in one repo. That instinct is wrong on its own, because a repository is a boundary for people, not for services.
A team of three to eight engineers working on a product with several connected services almost always moves faster with one repository. Everyone can see every change. A pull request that touches the API and the worker that processes its output shows up as one diff, reviewed by one person, merged in one commit. Nobody has to coordinate two separate release timelines to release one feature.
That changes as headcount grows and ownership splits. Once a team owns a part of the system on its own, with its own on-call rotation and its own decision on when to release, a shared repository starts to slow that team down. Every unrelated change in another team's folder still shows up in their commit history, still triggers their CI, and can still block their merge queue if it breaks something they did not touch. At that point, separate repositories give each team a clear boundary that matches how the org actually makes decisions.
A simple rule: repository structure should follow your reporting structure and release ownership, not your service diagram. A single team owning five services should probably keep them in one repository. Five teams each owning one service should probably not.
Look at deploy coupling before you look at code sharing
The second input is how closely your services have to deploy at the same time as each other. This is the factor teams skip, and it is the one that causes the most problems when it is wrong.
If a change to your API almost always requires a matching change to your frontend, and the two have to be released together to avoid breaking each other, that is tight deploy coupling. A monorepo makes tight coupling easy to manage: one commit, one CI run, one deploy that moves both pieces at the same time. Splitting tightly coupled services into separate repositories does not remove the coupling. It just makes the coupling invisible until a mismatched deploy breaks something in production, because now two repositories have to be updated and released in the right order by two different people.
If your services genuinely deploy on independent schedules, separate repositories remove unrelated changes instead of adding risk. A billing service that changes once a quarter should not sit in the same repository, the same CI pipeline, and the same access list as a customer-facing app that is released several times a week. Bundling them together means the billing team's CI runs on every unrelated app change, and the app team's pull requests show billing history they have no reason to read.
A useful test: look at your last twenty production deploys. If most of them touched exactly one service, your services are already loosely coupled, and separate repositories will not cost you anything. If most of them touched two or more services at once, they are tightly coupled today whether or not your repository structure says so, and a monorepo will save you the extra coordination work.
Shared code tells you which option to choose
The third input is how often code actually moves between services: a validation function, a type definition, a client library, a design system component. This is where a monorepo is either worth its cost or becomes extra work with no benefit.
When shared code changes often and every service needs the new version immediately, a monorepo removes an entire category of coordination problem. There is no version to bump, no package to publish, no service silently running last month's copy of a shared function because nobody updated its dependency. The change goes into one commit and every service in the repository that uses it sees it in the same pull request.
When shared code is small and changes rarely, this benefit shrinks to almost nothing, and the cost of a monorepo (a larger checkout, slower search, more noise in the commit history) costs more than it saves. In that case a small internal package, versioned and published normally, does the job with less overhead.
Google is the standard reference point for a monorepo working at real scale, and the actual numbers support the argument that structure and deploy strategy are separate decisions: Google's own engineers reported in Communications of the ACM that its monorepo holds roughly two billion lines of code across nine million source files, used by more than 25,000 developers, all in one repository. Google does not deploy that repository as one binary. It builds and releases thousands of independent services from it, using build tooling that tracks precisely which files a change touched so only the affected pieces rebuild and retest. The repository structure and the deploy strategy are two different decisions, and Google's scale only works because of custom tooling most teams have no reason to build. The lesson: the repository structure and the release process solve different problems, and you need a real answer to both.
How AI coding agents change the decision
The newest input in this decision did not exist five years ago. An AI coding agent that writes code across your repository has a working memory limit, called a context window: the amount of text it can hold and reason about at one time. When a change covers several services, a bigger context window lets the agent read all the related code, understand how the parts connect, and make the change consistently across every file, instead of writing each service's edit separately and hoping the parts still work together when a person combines them.
That limit used to be a real constraint. It has grown fast: Anthropic's own announcement states that Claude Sonnet 4 supports up to 1 million tokens of context, a fivefold increase from its prior 200,000-token limit, enough in the company's words to hold "over 75,000 lines of code" in a single request. A change that touches an API contract, the client that calls it, and the shared type definition between them now fits inside one working session for the agent, in one repository, where it can see all three files at once.
That capability matters most when those three files live in one place. A monorepo lets an agent open the API, the client, and the shared type at the same time, make a change that keeps all three consistent, and submit it as one reviewable pull request. In a polyrepo setup, the same change requires the agent, or the engineer directing it, to work across separate checkouts, separate pull requests, and separate CI pipelines, then manually verify the pieces still agree with each other after each one merges on its own schedule. The agent does not remove the coordination problem in that setup. It just does the typing faster while the coordination problem stays exactly as manual as it always was.
This does not mean every team should move everything into one repository because an agent can handle the resulting size. It means the point where a monorepo starts to be worth its cost, measured in team size or deploy coupling, has moved. Cross-service refactors that used to need a senior engineer coordinating three pull requests by hand can now be one agent session against one repository, provided the code the change touches actually lives inside the context window. A large enough monorepo will still exceed even a 1-million-token window; the benefit is real but not limitless.
A short decision rule
Put the four inputs together and the choice gets simpler than most teams expect.
Pick one repository when a small team owns several tightly coupled services, when most deploys already touch more than one of them, and when shared code changes often enough that services running different versions of it is a real risk. This is also the setting where an AI coding agent gets the most benefit from a monorepo, because a cross-service change fits in one context window and arrives as one change to review.
Pick separate repositories when ownership has split across teams with independent release schedules, when most deploys already touch exactly one service, and when the code shared between them is small and stable. Splitting here removes unrelated changes from each team's view without removing any coordination you actually needed.
Neither structure is a fixed decision. Plenty of systems start as one repository while the team is small and the services are tightly coupled, then split specific pieces out once a team, a release schedule, or a security boundary genuinely diverges. The real mistake is picking a structure based on what a well-known company does at a completely different scale, then keeping it long after your own team size, deploy pattern, or agent-assisted workflow no longer matches the reasons that structure made sense.
A repository should match how your people and your deploys are organized, and it should change when they change.
Sources
- Why Google Stores Billions of Lines of Code in a Single Repository, Communications of the ACM: supports the figures on Google's monorepo scale (roughly two billion lines of code, nine million source files, more than 25,000 developers) and the point that repository structure and deploy strategy are separate decisions.
- 1M token context window, Claude blog (Anthropic): supports the figure on Claude Sonnet 4's context window (1 million tokens, a fivefold increase from 200,000) and the stated capacity of over 75,000 lines of code in a single request.


