Monorepo Architecture
Design monorepo boundaries for apps, packages, tooling, and teams.
Key takeaways
- A monorepo earns its value from easier coordination of shared contracts, builds, ownership, and release workflows, not from co-locating code.
- The boundary model separates apps, packages, tooling, infrastructure, and docs by purpose.
- Apps depend on packages, never the reverse; domain packages expose stable APIs rather than internal storage details.
- An ownership matrix must name who owns each app, who can change shared packages, who approves deployment config, and who resolves cross-app breakage.
- Watch for red flags: apps importing private files from other apps, shared packages turning into utility dumping grounds, and build scripts relying on local machine state.
A monorepo is not valuable because all code is in one place. It is valuable when shared contracts, builds, ownership, and release workflows become easier to coordinate.
Boundary Model
| Area | Purpose | Typical contents |
|---|---|---|
| Apps | Deployable products or services | Web apps, docs, admin, workers |
| Packages | Shared reusable code | UI, config, API clients, domain logic |
| Tooling | Build and developer automation | Scripts, lint rules, codegen |
| Infrastructure | Deployment and environment definitions | CI config, platform config, IaC |
| Docs | Operating knowledge | Architecture decisions, runbooks, handbooks |
Architecture Principles
- Apps depend on packages; packages should not depend on apps.
- Shared packages need owners and compatibility rules.
- Domain packages should expose stable APIs, not internal storage details.
- Tooling changes must be reviewed with the same seriousness as application code.
- Repository structure should make the most common work path obvious.
Ownership Matrix
| Question | Required answer |
|---|---|
| Who owns each app? | Team or accountable lead |
| Who can change shared packages? | Maintainer group and review rule |
| Who approves deployment config? | Platform or operations owner |
| Who resolves cross-app breakage? | Named escalation path |
Red Flags
- Every app imports private files from another app.
- Shared packages become dumping grounds for unrelated utilities.
- Build scripts rely on local machine state.
- No one knows which team owns a failing package.