A monorepo is popular for good reasons — one version of shared code, atomic changes across packages, a single place to search. It is also a shared commons, and commons need rules before they need tooling.
Where it goes wrong without rules
The first symptom is usually a shared utility package that everyone depends on and nobody owns, changed freely by whoever needed something slightly different that week, breaking a consumer they did not know existed. The second symptom is a build that takes longer every month because nothing enforces a boundary between packages that should be independent.
The rules we now set at the start
- Every package has a named owner, visible in the repository, who reviews changes to its public interface specifically.
- Dependency direction is enforced by tooling, not convention — a linting rule that fails the build if a package imports something it should not, rather than a wiki page nobody reads.
- Shared code changes go through a deprecation window when they affect more than one consumer: the old interface keeps working alongside the new one until every consumer has migrated, rather than breaking everyone in one commit.
- Build and test scope is limited to what actually changed, using the dependency graph, so a change to one package does not require rebuilding and retesting the entire repository every time.
Why this needs deciding early
Retrofitting ownership and boundaries onto a monorepo that has grown without them means untangling dependencies that have accreted for years, on a codebase everyone is still actively shipping into. Every project where we have done this later rather than at the start has cost more, without exception.
A monorepo does not remove the need for boundaries between teams' work. It just makes the boundaries invisible unless you draw them on purpose.
Where coding agents add a new pressure
An agent working across a monorepo can touch a shared package while implementing an unrelated feature, because it has access to the whole repository and no inherent sense of which parts are someone else's to change. The dependency-direction tooling that used to be a nice-to-have is now closer to load-bearing, because it is often the only thing catching that kind of cross-boundary edit before review.
What good looks like a year in
Teams can move at their own pace inside their own packages and only need to coordinate at the points the dependency graph says they must, which turns out to be a much smaller set of moments than an ungoverned monorepo would suggest.
