Zum Inhalt springen

Monorepo vs. Polyrepo: die echten Trade-offs

Die Monorepo-Debatte handelt nicht von Tools — sie handelt davon, wie dein Team über Projektgrenzen hinweg kommuniziert, deployt und Code teilt.

3 Min. Lesezeit
Vergleich der Repository-Struktur, Monorepo mit geteilten Paketen gegenüber separaten Polyrepo-Repositories

Jede wachsende Engineering-Organisation steht irgendwann vor der Monorepo-Frage. Ein großes Repository für alles, oder viele kleine Repositories — eines pro Service oder Bibliothek? Die Antwort ist nicht universell, und beide Ansätze ohne Verständnis der Trade-offs zu übernehmen, führt zu Schmerzen.

Was jeder Ansatz wirklich bedeutet

Ein Monorepo speichert mehrere Projekte in einem einzigen Repository. Ein Polyrepo gibt jedem Projekt sein eigenes Repository. Die Unterscheidung ist relevant für Dependency-Management, CI-Pipeline-Design und teamübergreifende Zusammenarbeit.

# Monorepo structure
my-company/
├── apps/
│   ├── web/            # Next.js frontend
│   ├── api/            # Express backend
│   └── admin/          # Admin dashboard
├── packages/
│   ├── ui/             # Shared component library
│   ├── utils/          # Shared utilities
│   └── config/         # Shared configs (ESLint, TS)
├── package.json
└── turbo.json

# Polyrepo structure
my-company-web/         # Own repo, own CI, own deps
my-company-api/         # Own repo, own CI, own deps
my-company-admin/       # Own repo, own CI, own deps
my-company-ui-lib/      # Published to npm registry
my-company-utils/       # Published to npm registry

Wo Monorepos gewinnen

Atomare projektübergreifende Änderungen

Wenn eine gemeinsam genutzte Bibliothek ihre API ändert, erlaubt das Monorepo, alle Konsumenten in einem einzigen Commit zu aktualisieren.

tstypescript
// ❌ Polyrepo: changing a shared library's API requires coordinated releases
// 1. Update ui-lib, bump version, publish to npm
// 2. Update web app, install new version, fix breaking changes
// 3. Update admin app, install new version, fix breaking changes
// 4. Hope nothing breaks between steps 1 and 3
 
// ✅ Monorepo: one PR updates the library and all consumers
// packages/ui/src/Button.tsx — change the prop interface
// apps/web/src/pages/Home.tsx — update usage
// apps/admin/src/pages/Dashboard.tsx — update usage
// All in one commit, one CI run, one review

Gemeinsame Konfiguration

jsonjson
// Monorepo root package.json
{
  "private": true,
  "workspaces": ["apps/*", "packages/*"],
  "devDependencies": {
    "typescript": "^5.3.0",
    "eslint": "^8.56.0",
    "prettier": "^3.2.0"
  }
}

Eine Version von TypeScript, eine ESLint-Konfiguration, eine Prettier-Konfiguration. Kein Drift zwischen Projekten.

Code-Auffindbarkeit

In einem Monorepo funktioniert die Suche nach allen Verwendungen einer Funktion mit einem einzigen grep. In einem Polyrepo musst du über mehrere Repositories hinweg suchen — und weißt womöglich nicht, welche ein bestimmtes Paket überhaupt nutzen.

Wo Polyrepos gewinnen

Unabhängiges Deployment und Skalierung

ymlyaml
# ❌ Monorepo CI — any change triggers checks for everything
# (unless you invest heavily in affected-project detection)
on:
  push:
    branches: [main]
jobs:
  test-all:
    runs-on: ubuntu-latest
    steps:
      - run: npm test --workspaces # Tests everything
 
# ✅ Polyrepo CI — only the changed service is tested and deployed
on:
  push:
    branches: [main]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - run: npm test # Tests only this service
  deploy:
    needs: test
    runs-on: ubuntu-latest
    steps:
      - run: npm run deploy # Deploys only this service

Team-Autonomie

Polyrepos geben Teams volle Kontrolle über ihre Technologiewahl, CI-Pipelines und Release-Rhythmen. Team A kann Vitest nutzen, während Team B Jest nutzt. Team C kann stündlich deployen, während Team D wöchentlich deployt.

Einfacheres Tooling

Monorepos brauchen spezialisierte Tools (Turborepo, Nx, Lerna, Bazel), um inkrementelle Builds, Task-Caching und die Erkennung betroffener Projekte zu handhaben. Polyrepos funktionieren von Haus aus mit Standard-Tooling.

Die Build-Tool-Steuer

Monorepos funktionieren nur gut mit ordentlicher Build-Orchestrierung. Ohne sie wachsen die CI-Zeiten linear mit der Größe der Codebasis.

jsonjson
// turbo.json — Turborepo task pipeline
{
  "$schema": "https://turbo.build/schema.json",
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**"]
    },
    "test": {
      "dependsOn": ["build"]
    },
    "lint": {},
    "typecheck": {
      "dependsOn": ["^build"]
    }
  }
}
shbash
# Only build and test projects affected by the current changes
turbo run build test --filter=...[HEAD~1]

Ohne Caching und Erkennung betroffener Projekte wird ein Monorepo mit 20 Paketen quälend langsam. Diese Investition ins Tooling ist der eigentliche Preis von Monorepos.

Entscheidungsrahmen

FaktorMonorepoPolyrepo
Teamgröße< 50 Engineers> 50 oder mehrere autonome Teams
Gemeinsamer CodeStarkes Teilen zwischen ProjektenWenig projektübergreifendes Teilen
Deployment-RhythmusÄhnlich über Projekte hinwegSehr unterschiedlich pro Team
Tech-StackGrößtenteils homogenDivers (unterschiedliche Sprachen)
Tooling-InvestitionBereit, Turborepo/Nx zu lernenWill Standard-Git + CI

Der hybride Ansatz ist ebenfalls gültig: ein Monorepo für eng verwandte Services, die Code teilen, mit separaten Repos für unabhängige Systeme.

Häufige Fehler

tstypescript
// ❌ Monorepo anti-pattern: circular dependencies
// packages/auth imports from packages/user
// packages/user imports from packages/auth
// Build order becomes impossible to resolve
 
// ✅ Extract shared types into a separate package
// packages/shared-types — no dependencies on other packages
// packages/auth — depends on shared-types
// packages/user — depends on shared-types

In Polyrepos ist der entsprechende Fehler, Services eng über gemeinsamen Datenbankzugriff oder synchrone API-Ketten zu koppeln, die eigentlich ein einziger Service hätten sein können.

Die wichtigsten Punkte

  1. Monorepos ermöglichen atomare Änderungen über gemeinsam genutzte Bibliotheken und all ihre Konsumenten hinweg
  2. Polyrepos geben Teams Autonomie über Tooling, CI und Deployment-Rhythmus
  3. Monorepos erfordern Investitionen in Build-Tools — ohne Turborepo oder Nx werden CI-Zeiten unerträglich
  4. Polyrepos erfordern Registry-Infrastruktur, um Bibliotheken über Repositories hinweg zu teilen
  5. Wähle basierend auf Teamstruktur und Code-Sharing-Mustern, nicht nach Trends
Wilfredo Rujel

Wilfredo Rujel

Full-Stack-Softwareentwickler

Diesen Beitrag teilenX