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.
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.

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:
Il vostro team platform mantiene un repo di shared-libraries di cui nessuno ha una chiara ownership
Il versionamento tra i servizi è derivato al punto che aggiornare la shared library è un progetto da due settimane
Un nuovo ingegnere non riesce a essere produttivo senza capire quale dei vostri 23 repo clonare per primo
I patch di sicurezza alle dipendenze condivise richiedono PR coordinate su una dozzina di repo, con un foglio di tracking
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.

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:
La frequenza di modifiche cross-service ha superato il 30% e i runtime CI si stanno allungando
Avete assunto platform engineer con la capacità di investire in tooling monorepo
Un incidente di blast radius ha rivelato che l'isolamento del vostro polyrepo era illusorio -- i servizi condividevano abbastanza infrastruttura da rendere l'isolamento un conforto, non una sicurezza
I segnali che la decisione attuale va bene per ora:
I team sono genuinamente indipendenti e il costo di coordinamento è basso
Il vostro peggior incidente non è stato causato da drift di dipendenze cross-service
La capacità di platform engineering non esiste per mantenere il tooling monorepo senza rallentare il delivery del prodotto
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.