Monorepos voltaram com força. Empresas como Google e Meta usam há décadas, mas o ferramental moderno — Turborepo, Nx, pnpm workspaces — tornou a abordagem acessível para times menores. A questão é: deve ser acessível para o seu time?
A resposta honesta é: depende de problemas reais que você tem agora, não de problemas teóricos que você pode ter no futuro.
O que monorepos resolvem bem
Compartilhamento de código sem fricção
Quando você tem um design system, uma biblioteca de utils, tipos compartilhados, ou configurações que múltiplos projetos usam, um monorepo elimina a dança de versões: você não precisa publicar um pacote para que outro projeto use a mudança. É uma importação direta.
// Em qualquer pacote do monorepo
import { Button } from '@company/ui'
import { formatDate } from '@company/utils'
import type { User } from '@company/types'
Refactoring atômico
Quando você muda a interface de uma função compartilhada, você atualiza todos os consumidores no mesmo commit. Sem breaking changes, sem versioning pain, sem projetos desatualizados usando API antiga por meses.
CI/CD mais inteligente com build incremental
Ferramentas como Turborepo e Nx detectam quais pacotes foram modificados e rodam apenas os testes/builds afetados. Em monorepos grandes, isso transforma pipelines de 20 minutos em pipelines de 3 minutos.
# Turborepo: roda apenas o que mudou
turbo run build test --filter='...[HEAD^1]'
O que monorepos não resolvem
Monorepos não tornam código ruim melhor. Se você tem dois projetos com arquitetura inconsistente, colocá-los no mesmo repositório não vai alinhá-los — vai expor os conflitos mais rápido.
Monorepos não substituem convenções de time. O compartilhamento de código só funciona se as convenções forem compartilhadas também. Sem isso, você tem acoplamento sem alinhamento.
Quando NÃO usar monorepo
- Você tem 1–2 projetos sem código realmente compartilhado
- Os projetos têm ciclos de deploy completamente independentes e nenhuma sobreposição de domínio
- Seu time não tem experiência com o tooling (o custo de aprendizagem é real)
- Você está numa fase de produto onde velocidade individual de cada projeto é mais importante que consistência entre eles
Turborepo vs Nx: a decisão prática
Turborepo
Melhor para: times que querem setup rápido, principalmente JavaScript/TypeScript, com foco em builds e tasks incrementais. API simples, configuração mínima, integra bem com Vercel.
// turbo.json — configuração mínima funcional
{
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": [".next/**", "dist/**"]
},
"test": {
"dependsOn": ["build"]
},
"dev": {
"cache": false,
"persistent": true
}
}
}
Nx
Melhor para: monorepos maiores, polyglot (múltiplas linguagens), times que precisam de geração de código, visualização de dependências, e capacidades de plugin. Mais poder, mais configuração.
# Nx: gera um novo projeto no monorepo
nx generate @nx/react:application my-app
# Visualiza o grafo de dependências
nx graph
Estrutura de um monorepo bem organizado
my-monorepo/
├── apps/
│ ├── web/ # Next.js app
│ ├── mobile/ # React Native
│ └── api/ # Node.js backend
├── packages/
│ ├── ui/ # Design system compartilhado
│ ├── config/ # ESLint, TypeScript, etc.
│ ├── utils/ # Funções utilitárias
│ └── types/ # Tipos compartilhados
├── turbo.json
├── pnpm-workspace.yaml
└── package.json
A regra de ouro: apps/ contém coisas que você deploya. packages/ contém coisas que você importa. Nenhum pacote deve depender de um app — mas apps podem depender de qualquer pacote.
A decisão
Se você tem ou está prestes a ter: múltiplos projetos com código realmente compartilhado, times que trabalham em mais de um projeto, e a necessidade de mudanças atômicas entre projetos — monorepo provavelmente vale o investimento.
Se nenhum desses se aplica, você está trocando simplicidade por complexidade sem ganho proporcional. Polyrepo funciona bem para muitas organizações — não há vergonha nisso.
A armadilha a evitar: adotar monorepo porque "grandes empresas usam" ou porque parece mais profissional. A decisão deve ser sempre sobre problemas reais que você tem hoje.