Monorepo vs Polyrepo for Microservices

architecturemonorepodeveloper-experiencetooling

Our microservices architecture had grown to 30+ services spread across separate repositories. Coordinating changes across services was becoming increasingly difficult.

Consolidate all services into a monorepo using Nx

Keep separate repositories (polyrepo)

Pros
  • Clear ownership boundaries
  • Independent deployment pipelines
  • Smaller repository size
Cons
  • Difficult to coordinate breaking changes
  • Shared code requires separate npm packages
  • Inconsistent tooling across repos
  • Harder to enforce standards

Use Git submodules

Pros
  • Maintains separate repos while allowing unified view
  • Can still have independent CI/CD
Cons
  • Git submodules are notoriously difficult to work with
  • Doesn't solve the shared code problem
  • Added complexity without clear benefits

A monorepo with Nx provides the best of both worlds: atomic commits across services, shared tooling and standards, easy code sharing, while still maintaining independent deployment capabilities. The improved developer experience and ability to refactor across service boundaries outweighs the learning curve of adopting Nx.

The Problem

With 30+ repositories, we faced several challenges:

  • Coordinating Changes: A breaking API change required PRs across 5-10 repos
  • Shared Code: Common utilities were copy-pasted or published as npm packages
  • Inconsistent Tooling: Each repo had slightly different linting, testing, and build configs
  • Onboarding: New developers needed to clone and set up multiple repos

Why Nx?

We evaluated several monorepo tools:

  • Lerna: Primarily for npm package management, less suited for services
  • Turborepo: Good for build caching but less opinionated about structure
  • Nx: Comprehensive tooling with great caching, code generation, and dependency graph

Nx won because of its excellent TypeScript support, powerful caching, and active community.

Migration Process

  1. Created new monorepo with Nx
  2. Migrated services one at a time, starting with least critical
  3. Consolidated shared code into libraries
  4. Updated CI/CD to use Nx’s affected commands
  5. Trained team on monorepo workflows

Results After 3 Months

  • Cross-service refactoring time reduced by 70%
  • Build times improved 50% thanks to Nx caching
  • Shared code usage increased (less duplication)
  • Onboarding time for new developers cut in half
  • Team reports higher satisfaction with development workflow

The migration was challenging but the benefits have been substantial.