Home / migration / MONOREPO-VS-SUBMODULES

Monorepo vs Submodules: Developer Experience Comparison

๐ŸŽฌ Real-World Scenarios

Scenario 1: New Contributor Joins

#### With Submodules ๐Ÿ˜ซ

# Step 1: Clone (5 min + understanding --recurse-submodules)
git clone --recurse-submodules https://github.com/larcjs/larc.git
cd larc

# Step 2: "Why am I in detached HEAD?" (15 min googling)
cd core
git status
# HEAD detached at 4f8d156...

# Step 3: Figure out how to work on code (10 min reading docs)
git checkout main
git pull

# Step 4: Realize every submodule needs this
./work-on-submodule.sh core
./work-on-submodule.sh ui
./work-on-submodule.sh apps
# ... repeat 8 times

# Total time: 30-45 minutes + confusion

#### With Monorepo ๐Ÿ˜Š

git clone https://github.com/larcjs/larc.git
cd larc
npm install

# Total time: 2-3 minutes
# Ready to code!


Scenario 2: Add Feature Across Core + Components

#### With Submodules ๐Ÿ˜ซ

# Step 1: Work on core
cd core
git checkout main
git pull
# edit files...
git add .
git commit -m "Add bus.broadcast() method"
git push origin main

# Step 2: Can't test with components yet! They don't have the change.
cd ../ui
git checkout main
git pull
git submodule update  # Still old core!

# Step 3: Wait for meta repo to update submodule pointer
cd ../
git add core
git commit -m "Update core submodule"
git push

# Step 4: NOW update components
cd ui
git submodule update  # Finally has new core
git pull
# edit files to use bus.broadcast()
git add .
git commit -m "Use new broadcast method"
git push origin main

# Step 5: Update meta repo again
cd ../
git add ui
git commit -m "Update components submodule"
git push

# Total: 5 separate git operations, 10-15 minutes
# Risk: Forgot to update meta repo, teammates can't get your changes

#### With Monorepo ๐Ÿ˜Š

# Edit both at once
cd packages/core
# add bus.broadcast()...

cd ../components
# use bus.broadcast()...
# Test immediately - works!

# One atomic commit
git add packages/core packages/ui
git commit -m "Add and use bus.broadcast() method"
git push

# Total: 1 git operation, 2 minutes
# Teammates get both changes together, always in sync


Scenario 3: Fix Bug Found in Production

#### With Submodules ๐Ÿ˜ซ

# Step 1: Which submodule has the bug?
cd larc
./pull-updates.sh --check
# Hmm, bug is in core...

# Step 2: Enter core, fix bug
cd core
git checkout main
git pull
# fix bug...
git add .
git commit -m "Fix critical bus memory leak"
git push origin main

# Step 3: Update meta repo
cd ../
git add core
git commit -m "Update core with memory leak fix"
git push

# Step 4: Deploy - but wait! Need to update production
cd /production/larc
./pull-updates.sh
# Oh no, forgot to update meta repo!
# Or did I? Let me check...
git log
cd core
git log
# Are these the right versions? ๐Ÿค”

# Total: 15-20 minutes, uncertainty

#### With Monorepo ๐Ÿ˜Š

cd packages/core
# fix bug...
git add .
git commit -m "Fix critical bus memory leak"
git push

# Deploy
cd /production/larc
git pull
npm install

# Done! One commit, one pull, clear history
# Total: 5 minutes, confident it's right


Scenario 4: Review Pull Request

#### With Submodules ๐Ÿ˜ซ

# PR says: "Update core and components"

# View PR #1 (core repo)
gh pr checkout 123
cd core
git checkout pr-branch
# review changes...

# View PR #2 (components repo)
cd ../ui
gh pr checkout 456
git checkout pr-branch
# review changes...

# View PR #3 (meta repo)
cd ../
gh pr checkout 789
# See: "Update core and components submodules"
# Wait, which commits exactly? Let me check...
git diff main --submodule

# Test together
./pull-updates.sh
npm run build  # Does this even work?
# "Error: Cannot find module @larcjs/core v1.1.2"
# Oh, need to wait for npm publish... ๐Ÿคฆ

# Total: 3 PRs, 20+ minutes, can't test before merge

#### With Monorepo ๐Ÿ˜Š

# One PR with all changes
gh pr checkout 123

# See everything together
git diff main

# Test immediately
npm install
npm run build
npm test

# Works!
gh pr merge 123

# Total: 1 PR, 5 minutes, tested before merge


Scenario 5: Onboard Junior Developer

#### With Submodules ๐Ÿ˜ซ

Day 1:
  • Clone repo (30 min explaining --recurse-submodules)
  • Explain git submodules concept (1 hour)
  • Explain detached HEAD (30 min)
  • Show them SUBMODULE-WORKFLOW.md (1 hour reading)
  • Practice with work-on-submodule.sh (30 min)
  • Total: ~3.5 hours before first code change
Week 1:
  • Junior dev forgets to checkout main (3 times)
  • Forgets to update meta repo after submodule change (2 times)
  • Pushes to detached HEAD and loses commits (1 time)
  • Senior dev spends 2 hours helping recover
Result: Frustrated junior dev, wasted senior dev time

#### With Monorepo ๐Ÿ˜Š

Day 1:
  • Clone repo: git clone ... && npm install (5 min)
  • Explain directory structure (10 min)
  • Make first commit (5 min)
  • Total: 20 minutes, productive immediately
Week 1:
  • Junior dev works like any normal git repo
  • No special knowledge required
  • No lost commits
  • Senior dev reviews PRs normally
Result: Happy junior dev, efficient team

๐Ÿ“Š Metrics Comparison

| Metric | Submodules | Monorepo | Improvement | |--------|-----------|----------|-------------| | Clone time | 3-5 min | 1-2 min | 2-3x faster | | Setup time (new dev) | 30-45 min | 2-3 min | 15x faster | | Cross-package feature | 15 min, 5 commits | 2 min, 1 commit | 7x faster | | PR review complexity | 3 PRs, can't test | 1 PR, can test | 3x simpler | | Risk of mistakes | High (many steps) | Low (standard git) | Much safer | | Onboarding time | 3-4 hours | 20 minutes | 9x faster | | Context switching | High (switch repos) | Low (one repo) | Better focus | | CI/CD complexity | High (8 repos) | Low (1 repo) | Simpler |


๐Ÿ’ฐ Cost Analysis (Team of 5 Developers)

Submodules

  • Daily overhead per dev: 10 min (submodule updates, detached HEAD fixes, context switching)
  • Weekly per dev: 50 min
  • Team per week: 250 min = 4.2 hours
  • Cost per year (at $100/hr): $100 ร— 4.2 ร— 52 = $21,840
Plus:
  • Onboarding: 3 extra hours per new dev ร— 2 new devs/year = $600
  • Bug fixes due to version mismatches: ~2 hours/month ร— 12 = $2,400
  • Total annual cost: ~$24,840

Monorepo

  • Daily overhead: ~1 min (standard git workflow)
  • Weekly per dev: 5 min
  • Team per week: 25 min = 0.4 hours
  • Cost per year: $100 ร— 0.4 ร— 52 = $2,080
Plus:
  • Onboarding: Standard (no extra cost)
  • Bug fixes: Rare (atomic commits prevent mismatches)
  • Total annual cost: ~$2,080
Savings: $22,760 per year ๐Ÿ’ฐ

๐ŸŽฏ Real Quotes from Developers

About Submodules ๐Ÿ˜ซ

"Git submodules are the closest thing to version control hell" - Reddit developer
"Every time I use git submodules, I feel like I'm fighting git instead of using it" - HN comment
"We migrated away from submodules. Best decision ever." - Tech lead at major company
"Git submodules: perfect in theory, nightmare in practice" - Stack Overflow answer

About Monorepos ๐Ÿ˜Š

"Switched to monorepo, developer happiness went way up" - Google engineer
"Monorepo lets us move fast without breaking things" - Facebook engineer
"One repo, one source of truth. Simple." - Shopify engineer

๐Ÿข Who Uses Monorepos?

Major companies that chose monorepos:
  • Google (2B+ lines of code in one repo!)
  • Facebook/Meta
  • Microsoft
  • Twitter
  • Uber
  • Airbnb
  • Shopify
  • Netflix (for frontend)
They're not using submodules. There's a reason.

๐Ÿš€ Migration Effort

Time Investment

  • Planning: 1-2 hours
  • Migration: 4-6 hours (one-time)
  • Testing: 2-3 hours
  • Documentation updates: 1-2 hours
  • Total: 8-13 hours one-time cost

Break-Even Point

At $100/hr, break even in:
  • Cost: $1,300 (13 hours)
  • Savings: $1,903/month
  • Break even: 0.7 months (3 weeks!)
After 3 weeks, you're saving ~$2,000/month in developer productivity.

๐Ÿค” Common Objections Answered

"But we want separate repositories for separate packages"

Answer: You can still publish separately! Packages publish to npm independently. Users don't see your internal structure.

"What about independent versioning?"

Answer: Monorepos support this. Use changesets or lerna. You can still do @larcjs/core v1.1.1 and @larcjs/ui v1.2.0.

"Won't the repo get huge?"

Answer: Not really. Code is small. Git is efficient. Facebook has 100GB+ repo, works fine. Yours will be <1GB.

"What about access control?"

Answer: Use CODEOWNERS file, branch protection, PR requirements. Modern GitHub/GitLab handle this well.

"We're already using submodules..."

Answer: Sunk cost fallacy. The best time to switch was before starting. The second best time is now.

โœ… Decision Matrix

| If you value... | Use... | |----------------|--------| | Developer happiness | Monorepo โœ… | | Fast onboarding | Monorepo โœ… | | Simple workflow | Monorepo โœ… | | Atomic commits | Monorepo โœ… | | Easy testing | Monorepo โœ… | | Simple CI/CD | Monorepo โœ… | | Cost savings | Monorepo โœ… | | Pain and suffering | Submodules โŒ |


๐ŸŽฏ Bottom Line

Your project goal: Make developers' lives easier Current setup (submodules): Makes developers' lives harder Solution: Use a monorepo Action: Run ./test-monorepo.sh and see for yourself!
"The best tool is the one that gets out of your way and lets you focus on building great software. Git submodules get in the way. Monorepos get out of the way."