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. Not because monorepos suddenly got simpler, but because context is becoming a much bigger part of the development environment.

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 already know some things about the application. They know where the API is, how authentication works, which database models are involved and probably which other application consumes the same 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 something like:

/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 a lot 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.

Repository Boundaries Are Also Context Boundaries

I've worked on systems where the frontend, API and other services were all in separate repositories. There are plenty of good reasons for doing that, especially once teams get larger.

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

Imagine:

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

You ask an AI agent to change something in frontend-repo, and it finds:

await api.updateRegistration(data);  

It can see that the frontend calls an API, 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 who's worked on the system for two years might already know all of that. The AI doesn't.

You can obviously give AI access to multiple repositories, and I'm sure tooling around that will continue to improve, but at some point you're basically rebuilding a shared view of the system anyway.

That's one reason monorepos are starting to look more interesting to me again.

Shared Business Logic Was Already Useful

Shared business logic was probably one of the strongest reasons I liked monorepos even before AI. There are always rules that multiple parts of an application need to understand:

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, publish a shared npm package, create another internal service or just accept that slightly different versions of the same rule are going to exist in different applications.

None of those are necessarily terrible, but they all add some 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 pretty useful: one obvious place to look.

Instead of trying to figure out which of three different implementations is correct, there's hopefully one package where that business rule lives.

Of course, "hopefully" is doing a lot of work there. A badly organized monorepo can still have five implementations of the same thing, which is really just the worst of both worlds.

Cross-Application Changes Are Where This Gets Interesting

This is probably where I see the biggest advantage with AI.

A feature that sounds simple can touch a surprising amount of the application.

For example:

Add waitlist support.  

That might actually mean:

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

Historically that could mean 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 modify 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 consume it and which tests are likely to break 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 else.

Types Become Part of the Context

I've always liked TypeScript mainly because it makes larger Javascript applications easier to maintain. With AI, I've started appreciating 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 in the codebase and try 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 is harder to let drift because the compiler complains when something no longer lines up.

This is one of the reasons I think good typing, schemas and shared contracts matter even more with AI. The AI doesn't have years of context in its head, so anything you can make explicit in the repository helps.

More Context Isn't Always Better

There is an obvious downside to giving AI more context.

More context isn't necessarily 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 exact 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 clear responsibilities. Dependencies should go in one direction. Shared code should actually be shared, and old code should eventually be removed instead of sitting around forever waiting for someone or some AI agent 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 Matter More When Changes Get Bigger

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 can be 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 the entire application.

Probably not ideal.

A monorepo can make testing cross-application changes easier because everything is available to the same CI system:

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 more useful when AI is generating more changes than engineers traditionally would. If the agent changes one shared package, the build system should be able to tell it exactly which applications and tests are affected.

The Build System Still Matters

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

npm test  

and accidentally test the entire company.

That doesn't scale.

If AI agents are going to work inside large repositories, the build tooling needs to understand 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 where Nx, Turborepo, pnpm workspaces, Bazel and similar tooling become pretty important.

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

Otherwise the extra context comes with a huge performance penalty.

Boundaries Still Matter

One of the common arguments against monorepos is that developers can access too much.

I think 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 might work.

Architecturally you 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 more like:

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 naturally 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.

Monorepos Still Aren't Always the Right Answer

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 also context boundaries.

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

The more 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