Monorepo is a bad idea
There’s this concept in the industry that all successful companies use monorepos, so in order to become as successful as them, yours should too. “Google works with monorepo. Facebook works with monorepo. We should work with a monorepo, to be like them one day!”
The truth is though, that no big company chose to use monorepo. They just ended up that way, and now unable to get out of this tangle. What other choice they have then, other than sell you this idea of monorepo as a success story, and let you drink the Kool Aid?
There’s no denying that companies like Facebook, Google and Twitter are successful. But that’s despite monorepos, and not thanks to them. In fact, they all have whole teams of brilliant, best-in-class engineers just to handle complications monorepo legacy brings. And monorepo is just that — a glorified legacy artifact.
In the following article I’d like to break down some of the so called “advantages” of having a monorepo.
“With multiple repositories you have to define what a project is. Monorepo just holds the entire codebase of your company”
Just to be clear, you want to force yourself to define what a project is, and if they’re related, why they’re related. If you’re not sure what your project is doing, something probably went wrong.
“Having to split a project because it’s too big or has too much history for your VCS is not optimal”
Splitting big projects is an absolute must. Big project only means big mess. And if the history of your project is too big for VCS — you’re in an even bigger mess.
“With a monorepo projects can be organized and grouped together in whatever way you find to be most logically consistent, and not just because your version control system forces you to organize things in a particular way“
My VCS, GitHub for the past 5 years, never “forced” me to do something (although it almost convinced me once to adopt a kitten).
But the most logical way to organize a project is… repository per project. Not a repository where you put everything mashed together.
“Monorepo reduces overhead from managing dependencies”
That’s true only if you’re writing everything in single language. And do you really think there’s one single language that fits all your needs?
And if you have more than one language in your project, which most companies will, this advantage doesn’t hold any water.
And yes, there are always exceptions, like companies that develop a single on-premise product.
“Monorepo makes projects easy to navigate”
This argument is not valid if you’re using something like GitHub/GitLab, where you can organize your projects into organisations, put tags on them, and be able to search over your code.
If you’re using Git or something else… How is it there, back in 2005?
Seriously, though, I made it a habit to put two tags at the very least on each GitHub repository, telling to which team and department (departments if you are a really big company) it belongs.
“With monorepo it’s easy to set up a development environment”
If your microservices are hard to set up or test, it’s not because you’re not using a monorepo. It’s because you didn’t invest into making it easy to run and test.
Put a few days into having a good README, a Dockerfile and a Docker Compose. Make it a priority to maintain them.
“With multiple repositories you must version dependencies between them. Most solutions are cumbersome and involve a lot of overhead”
Dependencies are hard. Monorepo won’t solve that. What monorepo does allow, though, is to break code which you don’t own, and have no idea how it works.
Use semantic versioning. When introducing changes, think for a few minutes if they are backward compatible. There’s no “silver bullet” for that.
“Monorepo allows atomic changes“
This is related to the previous point. What this actually means is that instead of breaking one projects, monorepo allows you to break a few at the same time. Yay!
What nobody mentions that you do loose with monorepo:
- Build tools — at a certain point conventional build tools, be it Maven, NPM, Gradle or
go buildeither become too slow or simply stop working. You’ll have to switch to special build tools such as Bazel or Lerna, which are much less used, and as a result much less documented, than the conventional ones.
- VCS support — most of the big players are using their own forks of VCS just to maintain the amount of files. One company I interviewed with was even very proud that they employ Git contributors just for that.
- CI/CD — most commonly used CI tools such as CircleCI/TravisCI built around the concept of a single project per repo. Do say goodbye to them, and be ready to either go back to Jenkins monstrosities or, even “better”, build CI of your own. And don’t forget to put CD on top.
You won’t become the next Google if you switch to monorepo. But you’ll certainly introduce a lot of challenges to your project, unless you have some engineers from one of the big companies with experience how to handle them (which is how some small-ish companies end with a monorepo, by the way).
- Separate your code into small repositories with well-defined boundaries.
- Maintain backwards compatibility
- Use semantic versioning
- Invest into README and tests
Update: June 2021
It’s been a year and a half since I wrote this article.
Monorepo is still a bad idea.
Those who read the comments to this article here or on HackerNews could notice that many of them focus on “you should simply use our tooling to manage monorepo”.
And that’s precisely the problem you’ll be facing with monorepo. Instead of depending on convenient build, CI, CD and VCS tools, you’ll have to adopt tooling very few companies in the industry use. That tooling will have almost zero documentation. Since it’s controlled by a single company or two, it will contain leaky abstractions (
java_test in Bazel is just one example) that probably won’t suit your needs. Good luck with that.
And there are also some projects with “Peter Pan syndrome” that think they “will never grow up”. “Monorepo works great for us now, so it will work great for us in the future!”. No, it won’t. But by the time it grows too big and inconvenient, you won’t be able to do anything about it. Adopting or developing monorepo tooling will take months of work from your developers, which probably at that point you won’t be able to afford.
Don’t adopt monorepo. It’s a bad, bad idea.