Monorepo vs polyrepo: Guide för växande utvecklarteam

Summary

Monorepo eller polyrepo? Valet beror inte på antalet lagerkällor utan på hur tätt kopplad din kod är och hur mycket koordinering du är villig att hantera. Den här guiden går igenom verkliga avvägningar mellan arkitekturerna, signaler som pekar åt ett håll eller annat, och ett praktiskt ramverk för att fatta rätt beslut för ditt växande team.

Abstrakt visualisering av monorepo kontra polyrepo-arkitektur med förgreningskoddatabasdiagram

Monorepo vs polyrepo är en debatt som dyker upp igen varje gång ditt utvecklarteam växer snabbare än byggtiderna. Det korta svaret: ett monorepo vinner när team delar kod regelbundet och koordinerar ändringar på en gemensam yta; ett polyrepo vinner när team är verkligt oberoende och distribuerar utan att någonsin vänta på varandra. Allt däremellan beror på hur tätt kopplad din tjänstkod faktiskt är, och hur mycket koordineringsöverhead du är villig att absorbera. Den här guiden går igenom verkliga avvägningar, signalerna som pekar åt ett håll eller annat, och ett praktiskt ramverk för att fatta beslutet.

Den verkliga frågan handlar om koppling, inte antalet lagerkällor

De flesta monorepo vs polyrepo-debatter börjar med fel fråga. Antalet lagerkällor är inte problemet. Problemet är om dina team behöver röra sig tillsammans.

Om team A:s ändringar regelbundet kräver att team B uppdaterar något under samma releasecykel, har du tätt kopplat arbete. En lagerkälla för det är nästan alltid det renare svaret. Om team A och team B skickar på sina egna scheman, rör olika delar av systemet och aldrig väntar på varandra, separata lagerkällor är det genuint meningsfullt.

Det värsta möjliga resultatet: två separata lagerkällor för kod som fortfarande måste distribueras tillsammans. Du får all koordineringskostnad för ett monorepo utan någon av fördelarna. Dina team slutar med att öppna pull requests i lagerkälla A och lagerkälla B samtidigt, i hopp om att båda klarar CI-testerna på samma gång. Det här mönstret är överraskande vanligt i organisationer som valde polyrepo tidigt och sedan låtit sina tjänster bli mer beroende av varandra än ursprungligen planerat.

Det första steget innan du väljer något är att rita en enkel beroendeöversikt. Lista alla tjänster eller paket du äger och rita pilar där en beror på en annan. Om pilarna formar ett tätt kluster, tillhör det klustret en lagerkälla.

Utvecklarteam samlade runt en whiteboard som granskar kodarkitekturdiagram

Varför Google, Meta och Microsoft alla landade på monorepo i stor skala

Google håller det mesta av sin kod i en enda lagerkälla som uppskattas till över 80 TB data och 2 miljarder kodrader. Meta och Microsoft gör detsamma för sina kärnproduktöverflöden. Det är inte för att stora företag älskar komplexitet – det är för att i stor skala blir det att hålla beroenden synkroniserade över hundratals lagerkällor ett heltidsarbete för ingenjörer.

En enskild API-ändring i ett delat bibliotek kan kräva koordinerade uppdateringar över 40 olika lagerkällor. I ett monorepo är det en pull request. En granskning. En sammanslagning. En återställning om något går fel.

Enligt forskning publicerad av Sourcegraph använder 63 % av företag med 50 eller fler utvecklare nu ett monorepo för åtminstone en del av sin kodbas – en kraftig ökning från siffror för tre år sedan.

Den konkreta fördel som är viktigast: atomära commits. När en brötande ändring i ditt API också kräver uppdateringar på front-end och back-end, låter ett monorepo dig landstiga alla tre ändringar i en PR, testa dem tillsammans och återställa alla tre som en enhet om något går fel. Med polyrepo öppnar du tre separata pull requests, väntar på tre separata granskningscykler och hanterar ett fönster där dina tjänster kör omatchade versioner.

Ett utvecklarteam rapporterade att de gick från sporadiska distributioner till mer än 40 appreleaser per vecka efter att ha migrerat sina front-end-paket till ett Nx-monorepo. Angular-uppgraderingar som tidigare tog månader blev rutinuppgifter som team hanterade utan att stoppa annat arbete.

Polyrepo:s dolda koordineringskostnad

Polyrepo har verkliga fördelar värd att ta på allvar. Varje team kontrollerar sin egen CI/CD-pipeline, sin egen releasecykel, sina egna åtkomstkontroller. Säkerhet och efterlevnadsteam föredrar det ofta: åtkomst till kod kan begränsas till namngiven personal på en per-lagerkälla basis, vilket är viktigt inom reglerade branscher. Komponenter med öppen källkod lever renare i sina egna offentliga lagerkällor utan att exponera intern kod.

För team som är verkligt oberoende är dessa fördelar verkliga. Ett litet tjänsteteam som äger en datapipeline som körs på sitt eget schema och rör ingen delad kod har lite att vinna på att sitta inuti ett större monorepo.

Men polyrepo-organisationer samlar tystnadsfullt kostnader som inte dök upp i det ursprungliga beslutet. Beroendeversionering över lagerkällor blir sin egen disciplin. Ett delat verktygsbibliotek blir inaktuellt i vissa lagerkällor medan det förblir aktuellt i andra. Någon måste underhålla en kompatibilitetsmatris bara för att veta vilken version av vilket bibliotek fungerar med vilken version av vilken tjänst.

Ett värdefullt mätväl: mediandrivtidscykel i monorepo löper omkring 19 timmar, jämfört med cirka 2 timmar i polyrepo. Pull requests i monorepo tenderar att vara större för att de rör mer ytor, vilket saktar granskningen. Men när en polyrepo-ändring kräver tre koordinerade pull requests över tre lagerkällor för att landa en enskild funktion, överskrider den samlade cykeltiden ofta monorepo-siffran ändå – med den ökade risken för partiella sammanslagningar som lämnar tjänster i inkonsistenta tillstånd.

Mönstret som överraskar team: "vi började med separata lagerkällor för oberoende, men nu kräver varje release att öppna pull requests på fyra ställen." I det läget har du det värsta av båda världarna.

Byggkvalitet slutade vara den avgörande faktorn 2024

Den klassiska invändningen mot monorepo var byggkvalitet. Om ditt lagerkälla har 200 paket och du ändrar en fil, vill du verkligen bygga om alla 200?

Det argumentet löpte ut någonstans omkring 2022 till 2024, beroende på din stack.

Moderna byggverktyg använder innehållsmedveten cachning. De bygger bara om det som ändrades och hoppar över allt med identiska indata. En ändring i paketet payments utlöser inte en ombyggnad av design-system om ingenting i design-system ändrades. GitHub Actions tillhandahåller 10 GB kostnadsfri cachelagring innan du behöver en betald fjärrcache-lösning.

Turborepo hanterar de flesta JavaScript- och TypeScript-team väl upp till omkring 20 paket. Konfigurationen är en enda turbo.json, fjärrcachning fungerar kostnadsfritt på Vercel eller själv-hostades, och inlärningskurvan är låg nog för att ett team kan vara produktivt inom en dag.

Past 20 packages, eller när bygget sträcker sig över flera språk, tenderar Nx:s mer strukturerade approach att rättfärdiga den brantare inlärningskurvan. Nx lägger till kodgenerering, automatisk CI-distribution och fin-kornig beroendeövervakning som blir allt mer värdefull när lagerkällan växer.

För mycket stora organisationer som kör tusentals paket över flera språk är Bazel (Googles öppen källkod byggsystem) det enda verktyget designat för den skalan. Inställningskostnaden är betydande och kräver nästan alltid ett dedikerat plattformsarbetsgrupp.

Flera parallella distributionspipelines som flödar från en central kodbas, abstrakt DevOps-infrastrukturkoncept

Fyra frågor som löser debatten för ditt team

Det finns ingen universell rätt svar, men det finns ett tillförlitligt ramverk.

1. Delar dina team kod som ändras ofta? Om ja – ett delat designsystem, ett delat API-klientbibliotek, delad autentiseringslogik – är ett monorepo nästan alltid det bättre valet. Att hålla ett delat bibliotek synkroniserat över flera lagerkällor kräver konstant disciplin och driver nästan alltid.

2. Distribuerar dina team oberoende? Om team A:s tjänst skickas på tisdag och team B:s skickas på torsdag utan någon behövlig koordinering, tjänar polyrepo sin plats. Om release av en tjänst kräver samtidig release av en annan, tillhör den kopplingstypen ekvationen.

3. Hur många ingenjörer rör denna kodbas? Under 20 ingenjörer spelar lagerkällstruktur mindre roll än du tror. Över 50, börjar koordineringskostnaderna för polyrepo ackumuleras synligt. Över 200, blir fallet för ett monorepo mycket starkt om inte team är verkligt siloed efter produkt och teknik.

4. Har du säkerhet eller efterlevnad som kräver att isolera kod per team? I reglerade branscher – finans, sjukvård, vissa regeringskontexer – kan åtkomst till kod behöva begränsas till namngiven personal. Den begränsningen kan åsidosätta de andra svaren. Om hard kodisoleringskrav är ett efterlevnadskrav är polyrepo inte ett val, det är en begränsning.

Om du svarade "ja" på fråga 1 och "nej" på fråga 4, är ett monorepo nästan säkert rätt val. Om du svarade "nej" på fråga 1 och "ja" på fråga 2, är polyrepo ett försvarbart val. Allt annat är en bedömningsfråga.

Vad mest växande team faktiskt landar på

Väldigt få mogna utvecklingsorganisationer verkar i någon av ytterligheter. Mönstret som dyker upp mest ofta: ett monorepo för kärnprodukten (front-end, delade bibliotek, back-end tjänster som beror på varandra), och separata lagerkällor för verkligt oberoende komponenter.

En datapipeline som körs på sitt eget schema och delar ingen kod med huvudprodukten tillhör utanför monorepo. Ett internt verktyg som underhålls av ett enfemögt arbetsgrupp tillhör utanför. Ett öppen källkod bibliotek som behöver offentlig synlighet tillhör utanför.

Det här är inte en kompromiss. Det är rätt svar på en fråga som sällan har ett rent binärt svar. Håll saker tillsammans som behöver röra sig tillsammans. Separera vad som är verkligt oberoende.

Det viktiga är att fatta beslutet medvetet, inte som standard. De flesta team som slutar med polyrepo-spridning valde det inte: de började en tjänst, sedan en annan, sedan en annan, och stannade aldrig för att fråga om dessa tjänster behövde leva tillsammans.

Verktyget som gör endera approach faktiskt arbeta

För monorepos:

För polyrepos:

Biscuit kan hämta konfigurationsfilen. Beslutet om vilken som ska användas kommer fortfarande ned till dessa fyra frågor.

Utvecklare som arbetar vid dubbel monitoruppsättning granskar pull requests i ett mörkt hemmakontor

Frequently asked questions

Vad är skillnaden mellan monorepo och polyrepo?
Ett monorepo håller all kod i en enda lagerkälla och är bra när team delar kod regelbundet. Ett polyrepo delar upp kod över flera lagerkällor och fungerar bäst för oberoende team som sällan koordinerar.
Vilken stora företag använder monorepo?
Google, Meta och Microsoft använder alla monorepo i stor skala. Googles monorepo innehåller över 80 TB data och 2 miljarder kodrader. 63 % av företag med 50+ utvecklare använder ett monorepo för åtminstone en del av sin kodbas.
Är byggkvalitet fortfarande ett problem för monorepo?
Inte längre – moderna byggverktyg som Turborepo och Nx använder innehållsmedveten cachning som bygger om bara det som ändrades, vilket eliminerar tidigare prestandaproblem.
Vilka verktyg gör monorepo praktiskt?
Turborepo är bra för JavaScript/TypeScript-team under 20 paket. Nx erbjuder fler funktioner för större projekt. Bazel är designad för mycket stora flerspråkiga lagerkällor på företagsskala.
Kan vi byta från polyrepo till monorepo senare?
Ja, men det krävs planering och en stegvis migration. Börja med att identifiera tätt kopplad kod och migrera den först, behåll verkligt oberoende komponenter i separata lagerkällor.