Google y Meta mantienen monorepos internos desde hace más de diez años, con un equipo de infraestructura de build que pocas empresas medianas replican. Turborepo, Nx y pnpm workspaces acercaron la práctica a equipos de diez personas. El resultado aparece cuando el monorepo resuelve un problema que el equipo ya tiene hoy.

Tres problemas justifican el cambio: código que importa más de un proyecto, un cambio de API que necesita cruzar paquetes en el mismo deploy, y un CI que corre todo desde cero en cada push.

Lo que resuelve el monorepo

Importar código sin publicar paquetes

El design system, las utilidades, los tipos compartidos y la configuración de lint viven en un paquete del workspace y entran por import directo. El equipo deja de coordinar versiones publicadas entre repositorios.

// en cualquier paquete del workspace
import { Button } from '@empresa/ui'
import { formatDate } from '@empresa/utils'
import type { User } from '@empresa/types'

Refactors que cruzan proyectos

¿Cambió la firma de una función compartida? Actualizas la función y los consumidores en el mismo commit. El monorepo elimina la ventana en que dos repositorios corren versiones distintas de la misma API. El libro Software Engineering at Google describe cómo la empresa opera este modelo a su escala, con su build system propio incluido.

CI que solo paga por el diff

Turborepo y Nx leen el grafo de dependencias y corren build y test solo en los paquetes que tocó el diff. La guía de caching de Turborepo documenta la clave de hash por paquete y el cache remoto, que lleva la ganancia al CI en la nube.

# build y test solo en los paquetes que tocó el diff
turbo run build test --filter='...[HEAD^1]'

Lo que no resuelve el monorepo

Un monorepo no arregla código malo. Dos proyectos con arquitecturas en conflicto siguen en conflicto en el mismo árbol de carpetas, y el conflicto aparece en el mismo pull request. Un monorepo tampoco reemplaza las convenciones del equipo. Sin reglas compartidas de lint, formato y estructura de carpetas, creas acoplamiento entre equipos que no se ponen de acuerdo.

Cuándo saltarse el monorepo

  • El equipo tiene uno o dos proyectos y ningún código compartido entre ellos.
  • Cada proyecto tiene su propio ciclo de deploy y los dominios no se superponen.
  • Nadie en el equipo operó Nx o Turborepo antes, y el trimestre no tiene margen para la curva de aprendizaje.
  • El producto cambia de dirección cada semana; la velocidad de cada proyecto pesa más que la consistencia entre ellos.

Turborepo o Nx

Turborepo

Un equipo de JavaScript y TypeScript que quiere cache y pipelines incrementales con poca configuración. La referencia de configuración cabe en pocas decenas de líneas, y la integración con Vercel es nativa.

// turbo.json
{
  "tasks": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": [".next/**", "dist/**"]
    },
    "test": { "dependsOn": ["build"] },
    "dev": { "cache": false, "persistent": true }
  }
}

Nx

Un monorepo más grande, con más de un lenguaje, o un equipo que quiere generación de código, visualización de grafo y plugins de framework. El modelo mental de Nx explica cache por operación e invalidación por hash de entrada. Más poder, más configuración que mantener.

# genera una aplicación React en el monorepo
nx generate @nx/react:application my-app

# abre el grafo de dependencias en el browser
nx graph

La estructura que reviso en cada PR

my-monorepo/
├── apps/
│   ├── web/           # Next.js
│   ├── mobile/        # React Native
│   └── api/           # Node.js
├── packages/
│   ├── ui/            # design system
│   ├── config/        # ESLint y TypeScript compartidos
│   ├── utils/
│   └── types/
├── turbo.json
├── pnpm-workspace.yaml
└── package.json

La regla que aplico en revisión: apps/ guarda lo que se despliega, packages/ guarda lo que se importa. Un paquete no importa de un app. Un app puede importar de cualquier paquete. La documentación de workspaces de pnpm muestra el pnpm-workspace.yaml que amarra el árbol.

La decisión

El monorepo entra en el plan cuando ya tienes, o estás a un trimestre de tener, múltiples proyectos con código compartido, equipos que trabajan en más de un proyecto, y cambios que necesitan romper un API entre paquetes en el mismo deploy. El monorepo queda fuera cuando ninguno de esos tres puntos aparece en la retrospectiva de los últimos tres meses.

Adoptar un monorepo porque una empresa grande lo usa importa poco para tu realidad: el modelo de ellos incluye un equipo de infraestructura de build que tú no tienes. La decisión vale por el problema de hoy. El polyrepo atiende bien a la mayoría de los equipos hasta que ese problema aparezca.