Monorepo vs Polyrepo Differenze: il calcolo che decide

Riassunto

Faros AI ha analizzato 320 team su 12 mesi: il PR cycle time mediano è 19 ore in monorepo contro 2 ore in polyrepo. Quel divario non risolve il dibattito. Lo risolve il rapporto di feature cross-service: sopra il 30%, il costo di coordinamento del polyrepo supera l'investimento in tooling del monorepo. Sotto quella soglia, l'isolamento vince. Il resto dipende da blast radius, rollout primitive e capacità del platform team.

Diagramma architetturale monorepo vs polyrepo -- albero unificato e cluster isolati su sfondo scuro

Le monorepo vs polyrepo differenze si riducono a una sola domanda: che percentuale delle vostre feature richiede modifiche su più di un confine di servizio? Se non conoscete quel numero, state prendendo una decisione infrastrutturale basata sulla preferenza del team, non sui dati. In un'organizzazione di 50 ingegneri, quella preferenza costerà a qualcuno una domenica.

Il punto chiave è il calcolo. Entrambi gli approcci impongono costi. La domanda è quali costi la vostra organizzazione riesce ad assorbire meglio -- il costo di coordinamento del polyrepo o l'investimento in tooling del monorepo.

I dati sul PR Cycle Time non chiudono il dibattito. Ma lo rendono meno vago

Faros AI ha analizzato 320 team di ingegneria su 12 mesi e ha rilevato che i monorepo hanno un PR cycle time mediano di 19 ore. I polyrepo: 2 ore.

Un divario di 9,5x al mediano. Al 90° percentile, il gap si stringe: 8,6 giorni contro 5,5 giorni -- ma entrambe le code sono lente. Anche la media converge: 3,6 giorni per il monorepo, 2,8 per il polyrepo.

Il controargomento è consolidato: i monorepo hanno build più veloci quando la cache funziona. Un team polyrepo che coordina una modifica cross-service su cinque repository, con cinque pipeline CI separate e cinque requisiti di sign-off CODEOWNERS, non chiuderà una PR in due ore nemmeno lui.

I dati catturano i cycle time delle PR tipiche, non i worst case cross-cutting. È una distinzione che conta. I team polyrepo citano la loro mediana (rapida, perché la maggior parte delle PR è isolata). Chi difende il monorepo cita il dolore del coordinamento tra repo (reale, e documentato nelle code P90). Entrambi hanno ragione su scenari diversi.

I dati non chiudono il dibattito. Lo descrivono con più precisione di quanto faccia l'intuizione.

SRE engineer che monitora le metriche di deployment con dashboard multipli

Il blast radius che non state calcolando

Quello che raramente compare nelle slide delle conference: in un monorepo, una dipendenza condivisa rotta atterra su ogni servizio che la importa, nello stesso commit, prima che qualcuno con ownership downstream abbia revisionato la modifica.

In un polyrepo, una versione di pacchetto rotta rompe i servizi che la aggiornano -- ma solo quando la aggiornano. Il blast radius è posticipato e limitato dalla scelta del consumer.

Questo conta per i rollout con SLO gate. Una libreria condivisa difettosa in un monorepo non vi dà una finestra canary. Vi dà un blast radius cross-service in un singolo evento di deploy. Il vostro error budget inizia a bruciare su più SLO contemporaneamente prima che la vostra automazione riesca a rilevare il pattern e innescare un revert.

In un polyrepo, il rollout di una modifica a una dipendenza condivisa è sequenziale per natura. Il Servizio A aggiorna e si osserva il suo SLO. Il Servizio B aggiorna tre giorni dopo. Il blast radius in ogni momento è limitato a chi ha già adottato la modifica.

La domanda non è quale struttura sia intrinsecamente più sicura -- è quale sia il vostro deployment primitive. Se l'unità di deployment è il servizio con il proprio SLO gate, il polyrepo vi dà un isolamento naturale. Se l'unità di deployment è la modifica atomica che atterra in modo consistente su frontend, API e background worker contemporaneamente, il monorepo vi dà quel coordinamento senza drift di versioning.

Perché i team polyrepo toccano un muro di coordinamento a 50 ingegneri

Il costo di coordinamento si accumula. Con 8 ingegneri, gestire quattro repository è fastidioso ma fattibile. Con 50, diventa un lavoro part-time per diverse persone.

Segnali concreti che il coordinamento polyrepo è diventato strutturale:

Nessuna di queste è una patologia inventata. Sono failure mode documentati di team che hanno raggiunto gli 80 ingegneri e hanno guardato indietro alle loro decisioni sui repo con rimpianto.

Il polyrepo funziona quando i team sono genuinamente indipendenti -- cicli di release diversi, stack tecnologici diversi, rotazioni on-call diverse. Quando i team condividono abbastanza codice da richiedere che una modifica in un servizio implichi ragionare su altri tre, l'isolamento per cui il polyrepo era stato scelto diventa il meccanismo che rende il coordinamento doloroso.

Il segnale organizzativo: contate quanti canali Slack esistono specificamente per coordinare release cross-repo. Se la risposta è più di zero, avete già iniziato a pagare il costo di coordinamento in modo sistematico.

Il costo reale di un monorepo al 95° percentile

Il dato P90 di Faros AI è istruttivo: 8,6 giorni per le PR in monorepo al 90° percentile. Non è un team lento -- è la conseguenza strutturale di modifiche cross-cutting ampie che richiedono coordinamento tra più code owner, matrici CI più estese, e cicli di review che attraversano confini organizzativi.

Google ha Bazel. Meta ha sviluppato Buck. Nx Cloud e Turborepo remote cache esistono perché l'investimento in tooling per far performare un monorepo non è banale. Un monorepo con 200 ingegneri senza affected-only build selection, caching distribuito e merge queue automatizzate produce run CI di 45 minuti su PR che toccano una funzione di utilità condivisa.

Il costo in tooling è reale e routinariamente sottovalutato. I team che operano con successo monorepo in scala hanno tipicamente assunto platform engineer specificamente focalizzati su quella infrastruttura. Retrofittare il tooling monorepo su un codebase in crescita mentre si fa anche product delivery è un drenaggio che si manifesta nella deployment frequency prima di apparire in un post-mortem.

Se il vostro platform team è già al limite, aggiungere la manutenzione del tooling monorepo è un impegno significativo -- non una scelta di configurazione.

Diagramma architetturale su lavagna con strutture di pipeline ramificate per monorepo e polyrepo

La regola del 30% che i team high-performing applicano davvero

Un'euristica utile dai team che hanno preso questa decisione deliberatamente: se più del 30% delle vostre feature richiede modifiche su più confini di servizio, il costo di coordinamento di un polyrepo supererà alla fine l'investimento in tooling di un monorepo ben gestito.

Sotto il 30% -- dove si trovano la maggior parte delle organizzazioni microservizi -- i vantaggi di isolamento del polyrepo di solito superano il costo di coordinamento. Le modifiche cross-service avvengono, ma non abbastanza frequentemente da rendere il tooling condiviso più conveniente dell'isolamento.

Questo è misurabile. Prendete gli ultimi sei mesi di PR mergate e contate quante hanno richiesto modifiche in più di un repository per rilasciare una singola feature rivolta all'utente. Quel rapporto è il vostro input. Non sarà preciso al decimale, ma sarà direzionale -- e direzionale basta per fermare il dibattito che va avanti sulla preferenza del team.

Un team con un tasso cross-service del 12% non ha bisogno di un monorepo. Un team al 38% e in crescita sta pagando un costo di coordinamento che continuerà ad accumularsi.

Come la strategia di rollout cambia il calcolo

C'è una dimensione di questa decisione che riceve quasi nessuna copertura: il vostro rollout primitive.

Se eseguite rollout percentuali con SLO gate -- portando una feature al 5% del traffico, osservando gli error budget, poi espandendo progressivamente -- il vostro calcolo del blast radius cambia a seconda che la feature si estenda su uno o più servizi.

In un polyrepo, un rollout multi-servizio richiede di coordinare lo stato del rollout tra i servizi. Il Servizio A può essere al 20% mentre il Servizio B è ancora allo 0%, creando stati inconsistenti genuinamente difficili da ragionare in condizioni di incidente. I feature flag aiutano, ma state ancora gestendo lo stato dei flag cross-service senza un'unica fonte di verità per il progresso del rollout.

In un monorepo con commit atomici, la feature atterra in modo consistente su tutti i servizi. Il rollout può essere ancora percentuale a livello infrastrutturale, ma il codice è consistente dal momento in cui avviene il deploy. I vostri SLO gate si attivano contro uno stato coerente.

I team che fanno molte feature atomiche multi-servizio, con rollout progressivi e rollback automatizzato su violazione SLO, trovano spesso che la consistenza del monorepo elimina un'intera categoria di incidente per cui il polyrepo non ha un nome preciso -- l'incidente di divergenza di stato cross-service che sembra un bug ma è in realtà un problema di coordinamento del deployment.

Cosa dirà davvero il post-mortem

La maggior parte delle organizzazioni di ingegneria finisce su un ibrido che nessuno chiama ibrido perché suona come un compromesso architetturale.

Uno o due monorepo per le superfici di prodotto strettamente accoppiate. Repository separati per i servizi genuinamente autonomi con cicli di deployment indipendenti, la loro rotazione on-call, e un team che non ha avuto bisogno di coordinare una modifica a una shared library da sei mesi.

I segnali per riconsiderare la vostra configurazione attuale:

I segnali che la decisione attuale va bene per ora:

Il post-mortem vi dirà in quale di questi scenari vivete davvero. Quel documento è di solito più onesto dell'architecture decision record che ha preceduto il sistema che descrive.

Domande frequenti

Qual è la differenza principale tra monorepo e polyrepo?
In un monorepo tutti i servizi risiedono in un unico repository con ciclo CI condiviso; in un polyrepo ogni servizio ha il proprio repo con pipeline e ownership indipendenti. La differenza pratica è dove si accumula il costo: il monorepo paga in tooling e coordinamento cross-owner; il polyrepo paga in drift di versioning e overhead di coordinamento cross-repo a scala.
Quando conviene scegliere il monorepo?
Quando più del 30% delle vostre feature richiede modifiche su più di un confine di servizio. Sopra quella soglia, il costo di coordinamento del polyrepo supera l'investimento in tooling. Il monorepo richiede platform engineer dedicati e strumenti come Bazel, Nx o Turborepo per non degradare i tempi di build a scala.
Il polyrepo scala meglio del monorepo?
Non in modo assoluto. Il polyrepo scala bene quando i team sono genuinamente indipendenti. Tra i 50 e gli 80 ingegneri, se i servizi condividono dipendenze e feature cross-cutting, il costo di coordinamento diventa strutturale: versioning driftato, PR che richiedono tracking manuale, patch di sicurezza che impiegano settimane a propagarsi.
I dati Faros AI mostrano che il polyrepo è piu veloce. Vale sempre?
I dati (320 team, 12 mesi) mostrano una mediana di 2 ore per PR in polyrepo contro 19 ore in monorepo. Ma catturano le PR tipiche, non le worst-case cross-cutting. I team polyrepo hanno una mediana bassa perché la maggior parte delle loro PR è isolata; le code P90 del monorepo sono alte per le modifiche che attraversano ownership. Sono scenari diversi.
Come misuro se il mio team ha bisogno di cambiare approccio?
Contate le PR degli ultimi sei mesi che hanno richiesto modifiche in piu di un repo per rilasciare una singola feature utente. Se quel rapporto supera il 30%, siete in territorio monorepo. Se avete canali Slack dedicati al coordinamento cross-repo, state gia pagando il costo sistematicamente.
Il monorepo cambia il calcolo del blast radius?
Significativamente. In un monorepo, una dipendenza condivisa rotta atterra su tutti i servizi che la importano nello stesso commit. Non avete una finestra canary: il blast radius è atomico. In un polyrepo, il rollout di una modifica a una dipendenza è sequenziale per natura -- ogni servizio decide quando aggiornare, limitando l'esposizione simultanea.
Esiste un approccio ibrido valido?
Si, ed è quello dove finisce la maggior parte delle organizzazioni mature: uno o due monorepo per le superfici di prodotto strettamente accoppiate, repository separati per i servizi genuinamente autonomi. Non è un compromesso per mancanza di decisione -- è una struttura che riflette l'effettivo grado di accoppiamento dei team.