For me the complexity comes when you have many isolated projects sharing code. With a mono-repo that shared code is immediately consumed by all isolated projects, most of which the developer is not actively looking at to look for breakages.
This means that every single commit every single test suite has to be run across the whole organization. For a small startup that's probably fine, but for a larger organization that adds a ton of issues and extra time. If your change to a shared project breaks another project that you may not be familiar with you end up not only with a delayed context switch (since you don't know about it until the CI has finished running all tests across the whole org), but now you have to figure out how to address it before someone else changes code in that shared project which causes a merge conflict.
Compare that to a split-repo setup where projects are sharing code indirectly (via package management systems). When you change code other projects will only consume the new code when they actually upgrade their packages, and usually a developer that is familiar with the code base will actively hit that breakage in real time.
Granted, this has its own trade offs such as all your systems may be running different versions of shared code, and the delay in breakage detection can cause some back and forth in breakage between isolated projects.
This to me sounds like a break down of documentation and software architecture patterns, not so much a flaw of a monorepo. I’d rather it come up at that stage anyway even if it’s a pain, because it will help re-enforce better patterns and documentation as people feel these pain points. Shared libraries should have a code owner that is responsive for this if it’s not agreed that it’s straightforward enough to work on as an individual dev no?
That why I mentioned Bazel, once monorepo reach certain size you need to invest in right tooling. What people do instead is splitting into multi-repo and keep using the same tooling. By splitting repo you exchange easy problem of scaling tooling for very hard multi-repo/micro-service/coordination. IMO, the biggest problem with splitting repo is Conway Law, once split you change important dynamics of product development.
This means that every single commit every single test suite has to be run across the whole organization. For a small startup that's probably fine, but for a larger organization that adds a ton of issues and extra time. If your change to a shared project breaks another project that you may not be familiar with you end up not only with a delayed context switch (since you don't know about it until the CI has finished running all tests across the whole org), but now you have to figure out how to address it before someone else changes code in that shared project which causes a merge conflict.
Compare that to a split-repo setup where projects are sharing code indirectly (via package management systems). When you change code other projects will only consume the new code when they actually upgrade their packages, and usually a developer that is familiar with the code base will actively hit that breakage in real time.
Granted, this has its own trade offs such as all your systems may be running different versions of shared code, and the delay in breakage detection can cause some back and forth in breakage between isolated projects.