Thoughts on monorepos
DRAFT
This is still a work in progress…
TL;DR
I think this probably lines up with a Conway’s Law approach; for most mid-sized organizations Monorepos will be most effective when they live at the team/domain boundary.
Background
Over the last several years it seems like the sentiment towards monorepos has gone through cycles of wax and wane, with a lot of the arguments unchanging over time it doesn’t seem like there’s a clearcut answer to whether/where they should be used.
Having worked on a few web projects (primarily frontend JS, Node, and Go) employing the Monorepo pattern (some very successfully and others less so 😬) I wanted to note some of the things that the successful projects had in common and identify where I think they can be effectively used.
What are Monorepos?
TL;DR: A Monorepo (“monolithic repository”) is a single repository that houses multiple separate projects
As above, a Monorepo is a collection of separate projects that could live on their own but are co-located in the same repository. Different approaches range from companies like Google and Meta who keep massive company wide monorepos to monorepos that contain a single project with some chunks refactored into independantly publishable libraries.
In the best cases they allow for:
- Easier code sharing
- Simplified dependency management with atomic changes
- Unified tooling
- Streamlined development
However, they also often bring downsides like:
- Additional complexity
- Often require new tooling to manage the monorepo (Lerna, Turbo, NX, etc.)
- Standard tools (Git, IDEs, etc.) can struggle with large Monorepos
- Can lead to slower build/CI times
- Lack of isolation can increase risk of unrelated work causing cross-team impacts
Approaches to Monorepos
There are several ways that the Monorepo pattern can be applied
Whole Company Monorepos
DISCLAIMER: I’ve never worked at an organization that practised this, so the following is based soley on public reporting
Example: Google, Meta, Microsoft
Description: A single repository contains all of the company’s code, spanning multiple domains, teams, services, and tech stacks.
Pros: Maximum code reuse, unified tooling, and seamless cross-team collaboration.
Cons: Requires extensive tooling to handle scale, potential for slow operations, and complex permission management.
Single Domain Monorepos
Example: A monorepo for all frontend applications of a company.
Description: All code related to a specific domain (e.g., frontend apps, backend services, or DevOps scripts) is housed in a single repository.
Pros: Encourages domain-specific consistency and efficiency while keeping scope manageable.
Cons: Still requires careful dependency and versioning management, doesn’t account for projects that span domains (e.g. if the frontend is in one monorepo and the backend in another)
Single Team Monorepos
Example: A repository maintained by a specific team, covering all of their services and applications.
Description: Each team maintains their own monorepo, ensuring all their work is in one place.
Pros: Easier collaboration within a team, fewer permissions and process constraints.
Cons: Limits code sharing across teams, can lead to inconsistencies across an organization.
Single System Monorepos
Example: A monorepo containing all microservices related to a specific product.
Description: Instead of splitting microservices into separate repositories, a monorepo holds them all.
Pros: Simplifies managing interdependent services and streamlines deployments.
Cons: Requires careful CI/CD and dependency isolation strategies.
Final Thoughts
In my experience there’s a lot of benefit from having tightly coupled apps living in the same repo, especially if it’s likely that a team will want to release them atomically; however, trying to extend that to larger departmental/organizational level has enough tradeoffs that caution is advised.