The Case for Monorepos in the Age of AI

I've gone back and forth on monorepos over the years.

There are obvious benefits. Shared packages are easier, types can be reused, frontend and backend code can live closer together and you don't have to publish an internal package every time you change one interface.

There are also obvious downsides. The repo gets huge, build systems get more complicated, CI can get expensive and if boundaries aren't enforced properly everything eventually starts importing everything else.

AI changes the tradeoff a little bit though.

The more I've been using AI for development, the more I think having related applications in the same repository is becoming an advantage.

The More Context the Better

One of the biggest limitations with AI right now is context.

If I'm asking an engineer to change a feature, they usually have some existing knowledge of the application. They know where the API is, how authentication works, which database models are involved and probably know which other application is consuming the API.

AI doesn't necessarily know any of that unless you give it the context.

If everything is in one repository, it can potentially see:

/apps/web
/apps/admin
/apps/api
/packages/types
/packages/ui
/packages/utils
/packages/config

Now if I ask:

Add a new registration status and update the admin UI  

the AI can potentially find the backend enum, database schema, API response, shared TypeScript type and the frontend component using it.

That's much better than giving it access to only the admin repository and having it guess what the backend looks like.

For AI, context is basically part of the development environment now.

Separate Repositories Can Mean Missing Context

I've worked on systems where the frontend, API and other services were in separate repositories. There are plenty of good organizational reasons for doing that, especially with larger engineering organizations.

The problem with AI is that the repository boundary also becomes a context boundary.

Imagine this:

frontend-repo  
api-repo  
jobs-repo  
shared-library-repo  

You ask an AI agent to change something in frontend-repo.

It sees:

await api.updateRegistration(data);  

but it doesn't necessarily know what updateRegistration actually does, what validation happens on the backend or whether some background job gets triggered afterward.

A human engineer may already know because they've worked on the system for two years.

The AI doesn't.

You can obviously give it access to multiple repositories, but at that point we're slowly rebuilding something that looks a lot like a monorepo anyway.

Shared Business Logic Becomes More Useful

Shared business logic is probably one of the strongest reasons I've liked monorepos even before AI.

There are always rules that multiple parts of an application need to understand.

For example:

registration status  
permissions  
pricing rules  
validation  
date formatting  
API contracts  
sports-specific rules  

Without a monorepo you have a few choices.

You can duplicate the logic, create a shared npm package, create another internal service or just accept that slightly different versions of the logic are going to exist in different applications.

None of those are necessarily terrible, but they all add overhead.

In a monorepo you can do something like:

/packages/registration
/packages/permissions
/packages/types

and have multiple applications depend on the same implementation.

This also gives AI something very useful: a single source of truth.

Instead of the AI trying to determine which of three implementations is correct, there's hopefully one obvious package where that logic lives.

Of course the word "hopefully" is doing a lot of work there.

A badly organized monorepo can still have five different implementations of the same thing.

Cross-Application Changes Get Interesting

This is probably where I see the biggest AI advantage.

A feature that sounds simple can touch a lot of things.

For example:

Add waitlist support.  

That might mean:

Mongo schema  
→ API
→ business logic
→ admin application
→ registration application
→ email notification
→ background job
→ tests

Historically that might involve several pull requests across several repositories.

With a monorepo an AI agent can at least see the entire change.

That doesn't mean I would blindly let it change everything, but it can understand the dependency chain much better.

It can find where RegistrationTeam is created, where the API serializes it, which React components use the result and which tests are going to fail after the schema changes.

That's a lot more useful than asking an AI tool to modify one isolated piece and then discovering three repositories later that the change broke something.

Types Become Documentation for AI

I've always liked TypeScript primarily because it makes larger Javascript applications easier to maintain.

With AI I'm finding another benefit.

Types give the model clues about how the application is supposed to work.

For example:

type RegistrationStatus =  
  | "pending"
  | "accepted"
  | "waitlisted"
  | "cancelled";

is a lot more useful than having the model search through random strings across the codebase trying to figure out which values are valid.

If the frontend and backend share that type in a monorepo, even better.

The type starts acting like documentation that can't get quite as stale as a README because the compiler complains when something is wrong.

AI makes good typing and good schemas even more valuable for this reason.

Repository Structure Matters More

There is a downside to giving AI more context.

More context isn't always better if the context is garbage.

If your monorepo looks like:

/helpers
/helpers2
/common
/shared
/shared-new
/old-api
/api-new
/utils
/utils-final

the AI is probably going to have the same reaction a new engineer would have.

Which one am I supposed to use?

This is one area where I think AI actually increases the importance of good architecture.

Packages need obvious responsibilities.

Dependencies should go in one direction.

Shared code should actually be shared.

Old code should eventually be removed instead of sitting around forever waiting for someone to accidentally use it.

We used to organize code mainly so another engineer could understand it.

Now we're organizing it so another engineer and an AI agent can understand it.

Tests Become Even More Important

AI makes it very easy to change a lot of code quickly.

That's both the good part and the scary part.

An AI agent might modify six packages in a few minutes. If the repository has good tests, that's great because it can immediately run them and see what it broke.

If the repository doesn't have tests then you basically have a very fast junior engineer making changes across your entire application.

Probably not ideal.

A monorepo can make testing cross-application changes easier because everything is available in the same CI pipeline.

change package  
→ identify affected apps
→ build
→ unit tests
→ integration tests
→ E2E tests

Tools like Nx and Turborepo already do a lot of the dependency graph work needed to figure out what actually needs to run.

That becomes even more useful when AI is generating more changes than humans traditionally would.

The Build System Still Matters

The downside of a monorepo is that eventually somebody is going to run:

npm test  

and accidentally test the entire company.

That obviously doesn't scale.

If AI agents are going to work inside large repositories, the build tooling needs to know what actually changed.

If a shared UI component changes, maybe three applications need to rebuild.

If an API-only package changes, the marketing website probably doesn't care.

This is another place where tooling like Nx, Turborepo, pnpm workspaces and Bazel becomes important.

The AI should ideally be able to make a change and then run only the relevant builds and tests instead of treating a monorepo like one giant application.

Boundaries Still Matter

One argument against monorepos is that developers can access too much.

That's actually an even bigger concern with AI.

If everything is sitting next to everything else, it's very easy for an agent to take a shortcut.

Instead of calling the proper API it might import something directly from another package.

Instead of respecting a service boundary it might reuse an internal database model because it happens to be available.

Technically the code works.

Architecturally you've just created something terrible.

So I don't think the lesson is:

Put everything in one repo and let AI figure it out.  

It's closer to:

Put related things in one repo,  
but make the boundaries extremely obvious.  

AI needs guardrails just like developers do.

Probably more.

And Then There Are Layoffs...

There is also another slightly depressing argument for monorepos in the age of AI.

Companies have fewer engineers.

So... monorepos are better now?

I'm joking.

Mostly.

One traditional argument against monorepos was that with hundreds or thousands of engineers working in the same repository you need really good tooling, ownership rules and coordination.

If you have fewer engineers touching the codebase, some of those problems become smaller.

Meanwhile those same engineers are now using AI and potentially making changes across a much larger portion of the stack.

So we might end up with fewer humans touching more code.

Which weirdly makes the monorepo model make even more sense.

I don't know if that's progress or just the industry finding a creative way to make everyone responsible for more stuff.

Conclusion

I don't think AI suddenly means every company should move everything into one monorepo.

There are still good reasons to keep repositories separate. Completely independent services, different security requirements, different teams, different deployment models and different technology stacks can all justify separate repositories.

But I do think AI changes one part of the equation.

Repository boundaries aren't only organizational boundaries anymore.

They're context boundaries.

And when you're working with AI, context is extremely valuable.

The interesting question might not be whether monorepos are better than multiple repositories.

It might be:

How much of the system does the developer  
and the AI working with them  
need to understand to make a correct change?  

If the answer is "most of it," then having most of it in one place starts looking pretty attractive.

Comments powered by Disqus