Always Go With a Monorepo
I code, found, write, and<br>speak.
Veteran CTO who built successful companies through empathic leadership and mastery of software delivery - from sustainable code to stakeholder trust. Now exploring the future of empathic and sustainable tech.
Learn More
Always Go With a Monorepo
First published at Wednesday, 15 July 2026
Always Go With a Monorepo<br>This is a blog article out of a series where I reflect on what I learned during funding, growing (, and selling) SaaS product companies. While I write those things down for myself, since I believe self-reflection helps me learn, I also want to share my thoughts with anybody who might be interested. An overview of all related topics can be found below. I have a bunch of these blog posts lined up, so you also might want to follow me if you like this one.
I made this argument to my team again last week, as I have many times over the years. This time a team right next to us was busy doing the opposite: taking a working monorepo and splitting it into around eighty separate repositories. I think it will cost them dearly, and slowly, in a way that will be hard to attribute to the decision once the friction sets in.<br>So let me state the position as flatly as I hold it. Use one repository. Draw your boundaries inside it. Reach for a second repository only when you have a mechanical reason the filesystem genuinely cannot give you, and notice how rarely that turns out to be true.<br>You want a boundary, not a repository<br>When somebody proposes splitting a repository, listen to the reason. It is almost always about a boundary: this part should be isolated from that part, this team should own this and not touch that, this layer is reusable and that one is specific. These are good instincts. A system without clear internal boundaries turns to mud.<br>The mistake is the jump from "I want a boundary" to "I want another repository". A repository boundary is one way to draw a line, and it happens to be the most expensive one available. A directory is also a line. So is a module, a package, a review rule. The question is never whether you need a boundary. You do. The question is what the boundary has to do, and whether a repository split is the cheapest thing that does it. It almost never is.<br>It is the same reflex that drives teams to split a system into microservices before they need to, which I have written about separately: reaching for an expensive, hard-to-reverse structural boundary to get an isolation you could have had for almost nothing inside a single deployable. Repositories and services are different lines, but the error is identical.
Repository count is not an architecture decision<br>The number of repositories you have is not an architectural property of your system. The boundaries inside it are. You can take one well-structured codebase and split it across ten repositories without changing its architecture at all, only its logistics, and you will have made those logistics much worse.<br>Most advice on this hedges by scale: a monorepo for the big companies, separate repositories are fine for a small team. I think that gets it backwards. Google and Meta run enormous monorepos and pour real engineering into the tooling to keep doing so. The usual reading is "they are special, do not copy them". The more useful reading is that the coordination cost of splitting code across repositories is real enough that the largest engineering organisations on earth chose to fight tooling problems rather than pay it. If the polyrepo tax is heavy enough to bend Google toward one repository, it is certainly heavy enough to matter at your scale. Small teams have less slack to absorb that overhead, not more.
The cheap boundary: a directory and a review<br>In my current work we build a multi-tenant platform as a single repository, and the boundary that matters most, the line between what is reusable across tenants and what is specific to one, is drawn with top-level directories. A reviewer can tell from the file path alone which side of the line a change sits on. When something tenant-specific starts leaking into the reusable part, the path itself is the smell, visible in the diff before anyone reads a line of code.<br>That costs nothing. There is no second checkout, no version to pin, no release to coordinate. The boundary is as visible as a repository wall would have made it, and it moves with a simple file move when you get it wrong.<br>I will be honest about the trade-off, because it is the one real argument for splitting. A directory boundary is enforced socially, by review and convention, and at most by a CI check. Nothing at the language level stops a developer from importing across the line until something catches it. A separate repository enforces the same boundary mechanically: you cannot import what you have not declared as a dependency. That is a genuine difference. But you buy that one guarantee by paying the entire coordination tax below, and for an internal team...