Lesson 0006 · ~12 minutes

Deal-breakers: spot pain before you scale it

One skill: name the failure modes that turn a monorepo into a slower polyrepo — and the moon-shaped counters you already know.

Win for this lesson

In a design review you can reject “dump folders in git and hope,” flag full-CI thrash, missing ownership, and cache lies — and know when polyrepo is still the right call.

1. Collocation without tooling

Nx and monorepo.tools both insist: multiple projects in one repo without well-defined relationships is not a real monorepo — it is collocation. Symptom: every PR runs every test; nobody knows the graph. Counter: moon project graph + tasks + targets (lessons 2–4).

2. Full CI on every push

Cost scales with repo size, not change size. moon’s --affected (and graph-fed CI) only runs work whose inputs intersect VCS changes (run a task). Without that, monorepos lose to many small polyrepo pipelines.

3. Over-coupling / no boundaries

Google’s monorepo paper lists unnecessary dependencies and code-health cost as first-class downsides (CACM). Easy imports become spaghetti. moon’s constraints.enforceLayerRelationships and tagRelationships in workspace config exist to fail the graph when layer/tag rules break — use them before the tangle hardens.

4. Ownership vacuum

One repo does not mean one team. Without CODEOWNERS / project owners, reviews become random and drive-by breaks land unowned. moon can aggregate owners and sync CODEOWNERS ((codeowners). Polyrepo “repo = team” was ownership for free — monorepos must buy it back.

5. Cache lies (wrong inputs/outputs)

Smart hashing only helps if inputs/outputs match reality. Missing inputs → stale green. Phantom outputs → broken hydration. Inheritance without inputs (lesson 4) re-creates “always run.” Treat cache correctness as a product requirement, not a bonus.

6. Version drift (no pins)

Shared tasks on different Node majors is not standardization. Lesson 5: pin with .moon/toolchains + full semver; use force-globals only when CI/Docker already owns the binaries.

7. Migration cost denial

History, CI secrets, permissions, and habits do not vanish on moon init. Prefer incremental adoption; moon documents migrate helpers from Nx/Turborepo (setup workspace / extensions). Big-bang “merge all repos this Friday” is a deal-breaker unless the org already pays for a platform team.

8. When monorepo itself is wrong

Then polyrepo (or a later synthetic monorepo graph) is the honest choice — lesson 1 spectrum still holds.

Rule

A monorepo without graph, affected CI, ownership, and pins is often worse than polyrepo. Tooling is not optional décor.

9. Practice

Equal-length options. Spot the deal-breaker fast.

Question 1

Five apps land in one git root with ad-hoc scripts; CI runs all tests always. Best label?

Question 2

Apps start importing each other’s private internals freely. First moon-shaped counter?

Question 3

Strongest reason to keep polyrepo instead of monorepo?

Question 4

Builds report cache hits but miss real source edits. Likeliest cause?

10. Primary source

Recommended: re-skim What is a Monorepo? (collocation vs tooling) and the advantages/costs section of Google’s CACM monorepo paper. Keep the deal-breakers sheet for reviews.

Ask your teacher Stress-test a real monorepo (trio-moon or planned merge) against this list. Chat is part of the course.