Arquitectura · 26 de octubre de 2026 · Daniel Murillo
Monorepo: Bun Workspaces vs pnpm Workspaces vs Nx
Bun y pnpm gestionan paquetes; Nx orquesta tareas. Cómo elegir sin confundir capas ni añadir complejidad de más.
Un monorepo no necesita una herramienta compleja desde el primer día. La clave está en distinguir dónde viven los proyectos, cómo comparten dependencias y quién decide qué tareas deben ejecutarse.
Introducción
Cuando una aplicación crece, aparecen varios proyectos: frontend, API, librerías compartidas, herramientas internas y pruebas. Podemos mantenerlos en repositorios separados o agruparlos en un único repositorio: un monorepo.
Aquí suele surgir una confusión: Bun Workspaces, pnpm Workspaces y Nx se comparan como si hicieran exactamente lo mismo. En realidad, operan en capas distintas:
- Monorepo es una estrategia para organizar el código fuente.
- Workspaces permiten gestionar paquetes relacionados dentro de un repositorio.
- Bun y pnpm instalan dependencias, enlazan paquetes locales y ejecutan scripts.
- Nx coordina proyectos y tareas, identifica proyectos afectados y reutiliza resultados mediante caché.
Por eso, no siempre hay que elegir uno de los tres. Una combinación como pnpm + Nx o Bun + Nx puede tener sentido: el gestor de paquetes y el orquestador resuelven problemas diferentes.
La pregunta no es qué herramienta gana en abstracto, sino cuánta coordinación necesita el repositorio y qué complejidad vale la pena asumir.
1. ¿Qué es un monorepo y por qué existe?
Un monorepo contiene varios proyectos o paquetes en un único repositorio Git. No significa que todo sea una sola aplicación ni que todos los proyectos deban desplegarse juntos.
unio/
├── apps/
│ ├── web/
│ ├── api/
│ └── admin/
├── packages/
│ ├── ui/
│ ├── contracts/
│ ├── config/
│ └── utils/
├── package.json
└── README.md
Las aplicaciones pueden desplegarse por separado mientras comparten librerías y convenciones.
Ventajas
- Cambios coordinados: actualizar una librería y sus consumidores en el mismo commit.
- Código compartido visible: contratos, componentes y utilidades viven cerca de sus consumidores.
- Configuración consistente: linting, TypeScript, pruebas y convenciones pueden centralizarse.
- Refactors transversales: es más fácil adaptar varios proyectos a un cambio de contrato.
- Menos fricción con dependencias internas: los paquetes pueden referenciarse como workspaces.
Desventajas
- Repositorio más grande: clonar, indexar y navegar puede costar más.
- CI más pesada: sin una estrategia de tareas, cada cambio puede ejecutar builds y pruebas innecesarias.
- Límites poco claros: un monorepo no evita el acoplamiento ni las dependencias circulares.
- Propiedad y permisos: los equipos necesitan definir quién mantiene cada área.
- Despliegues heterogéneos: proyectos con diferentes runtimes, lenguajes o procesos de publicación requieren cuidado adicional.
Un monorepo es útil cuando los proyectos comparten código, contratos, prácticas o ciclos de cambio. Si son independientes, tienen permisos muy distintos y casi nunca comparten código, varios repositorios pueden ser más simples.
2. Qué resuelven los Workspaces
Los workspaces permiten declarar varios paquetes en un mismo repositorio y hacer que dependan unos de otros mediante nombres de paquete.
{
"name": "@acme/web",
"dependencies": {
"@acme/ui": "workspace:*"
}
}
El protocolo workspace: expresa que la dependencia debe resolverse contra un paquete local del monorepo. Cada paquete mantiene su propio package.json y declara las dependencias que utiliza.
Los workspaces ayudan con:
- Instalación coordinada.
- Enlace de paquetes locales.
- Un lockfile para reproducir la instalación.
- Ejecución de scripts en varios paquetes.
- Gestión de dependencias internas.
Pero un workspace, por sí solo, no es necesariamente un sistema completo de build. Puede ejecutar scripts, pero no siempre conoce qué proyectos han sido afectados por un cambio ni qué artefactos puede recuperar de una caché.
3. Bun Workspaces: sencillez dentro del ecosistema Bun
Bun soporta workspaces mediante el campo workspaces del package.json.
{
"name": "acme",
"private": true,
"workspaces": ["apps/*", "packages/*"]
}
Los paquetes internos pueden depender unos de otros con workspace:*. Bun permite instalar las dependencias desde la raíz y ejecutar scripts con filtros.
Ventajas
- Integración directa con Bun.
- Configuración familiar mediante
package.json. - Instalación y enlace de paquetes internos.
- Filtros para instalar o ejecutar scripts en paquetes seleccionados.
- Una solución ligera para proyectos pequeños y medianos.
Desventajas y límites
- Los workspaces no sustituyen por sí solos un orquestador completo.
- La selección de proyectos afectados y la caché de builds requieren otras capacidades o herramientas.
- Conviene validar compatibilidad con CI, publicación, bundlers y despliegue.
- Herramientas que esperan un lockfile o estructura de instalación específicos pueden requerir ajustes.
Cuándo elegirlo: si ya utilizas Bun y quieres gestionar paquetes locales con poca configuración. Si el repositorio crece y la CI repite trabajo costoso, puedes incorporar un orquestador después.
4. pnpm Workspaces: gestión explícita y eficiente de dependencias
pnpm permite organizar proyectos relacionados en un monorepo. La definición suele vivir en pnpm-workspace.yaml:
packages:
- "apps/*"
- "packages/*"
Un proyecto puede declarar una dependencia interna así:
{
"name": "@acme/web",
"dependencies": {
"@acme/contracts": "workspace:*"
}
}
pnpm utiliza un almacén de contenido compartido y enlaces para evitar duplicaciones innecesarias. Su modelo puede revelar dependencias que una aplicación utilizaba sin declararlas correctamente, lo que favorece manifiestos más precisos.
Ventajas
- Gestión eficiente del almacenamiento de dependencias.
- Buen soporte para paquetes locales y monorepos.
- Protocolo
workspace:explícito. - Filtros para ejecutar tareas en paquetes seleccionados y sus dependencias o dependientes.
- Ecosistema ampliamente utilizado en JavaScript y TypeScript.
Desventajas
- Algunas herramientas antiguas asumen una estructura plana de
node_modulesy pueden necesitar ajustes. - El equipo debe aprender la sintaxis de filtros y la configuración del workspace.
- pnpm gestiona dependencias y scripts, pero un orquestador dedicado puede aportar más control sobre grafos complejos y caché de builds.
Cuándo elegirlo: si quieres una base sólida para un monorepo JavaScript/TypeScript con dependencias explícitas y filtros útiles. Para muchos equipos, pnpm Workspaces basta al principio; Nx puede añadirse cuando la coordinación de tareas lo justifique.
5. Nx: entender y orquestar el monorepo
Nx cumple una función diferente. Puede trabajar sobre un monorepo existente que utilice pnpm, Bun, npm o Yarn. No es necesario reemplazar el gestor de paquetes.
Nx construye un grafo de proyectos y un grafo de tareas. Puede utilizar las dependencias entre aplicaciones y librerías para ordenar tareas, identificar proyectos afectados y decidir cuándo reutilizar un resultado de caché.
Imagina esta estructura:
apps/
├── web
└── api
packages/
├── ui
├── contracts
└── utils
Si solo modificas api, quizá no haga falta volver a construir web. Si modificas contracts, sí podrían verse afectados varios consumidores. Nx puede usar el grafo para ejecutar las tareas relacionadas con el cambio.
Caché de tareas
Cuando una tarea está configurada para ser cacheable, Nx calcula una huella a partir de sus entradas relevantes. Si esas entradas no han cambiado y existe un resultado válido, puede restaurar artefactos y salida en vez de ejecutar el trabajo otra vez.
La caché remota puede compartir resultados entre máquinas de desarrollo y CI, según la configuración y los permisos.
Ventajas
- Grafo de proyectos y dependencias.
- Ejecución ordenada de tareas.
- Selección de proyectos afectados con
nx affected. - Caché local y remota.
- Plugins, generadores e integraciones.
- Puede añadirse a un monorepo existente sin sustituir el gestor de paquetes.
Desventajas
- Introduce conceptos y configuración adicionales.
- La caché depende de declarar correctamente entradas, salidas y dependencias.
- Puede ser excesivo para un repositorio pequeño con builds rápidos.
- Los generadores y convenciones requieren disciplina.
- La caché remota requiere configuración adicional y puede depender de servicios externos según la modalidad.
Cuándo elegirlo: cuando hay muchas aplicaciones o librerías, builds costosos, dependencias entre proyectos y pipelines que repiten trabajo innecesario.
Nx no hace que el código de negocio sea automáticamente más rápido. Su valor está en reducir trabajo de desarrollo y CI y coordinar tareas.
6. Comparación directa
| Capacidad | Bun Workspaces | pnpm Workspaces | Nx |
|---|---|---|---|
| Función principal | Dependencias y paquetes con Bun | Dependencias y paquetes con pnpm | Orquestación de proyectos y tareas |
| Instalar dependencias | Sí | Sí | No es su función principal |
| Enlazar paquetes locales | Sí | Sí | Usa el gestor existente |
| Ejecutar scripts | Sí, con filtros | Sí, con filtros | Sí, con pipelines de tareas |
| Grafo de proyectos y tareas | Básico respecto a su función de workspace | Filtros basados en relaciones de paquetes | Grafo explícito de proyectos y tareas |
| Selección de proyectos afectados | No equivale a un sistema completo de affected | Filtros por paquetes; el flujo basado en cambios requiere configuración adicional | Sí, mediante nx affected |
| Caché de builds | No es su función principal | No es su función principal | Sí |
| Caché remota de tareas | Requiere otra herramienta | Requiere otra herramienta | Disponible mediante configuración compatible |
| Complejidad inicial | Baja | Baja a moderada | Moderada |
La comparación correcta no es «Bun o pnpm o Nx». Bun o pnpm pueden gestionar dependencias mientras Nx coordina qué tareas ejecutar y cuáles pueden reutilizarse.
7. ¿Necesito Nx desde el primer día?
Escenario A: pocos proyectos y scripts sencillos
Tienes una aplicación web, una API y una librería compartida. Los builds tardan poco y el CI es simple.
Recomendación: empieza con Bun Workspaces o pnpm Workspaces. Mantén scripts claros y evita una capa de configuración que todavía no aporta suficiente valor.
Escenario B: varias aplicaciones y librerías
Tienes frontend, backend, panel administrativo, UI, contratos y utilidades compartidas. Los builds comienzan a tardar y los cambios afectan a subconjuntos de proyectos.
Recomendación: usa Bun o pnpm para dependencias y evalúa Nx para coordinar tareas, seleccionar proyectos afectados y cachear resultados.
Escenario C: monorepo grande con varios equipos
Hay muchas aplicaciones, librerías, convenciones y pipelines. Se necesitan reglas arquitectónicas, generadores y caché remota.
Recomendación: Nx puede aportar valor si el equipo puede mantener su configuración y entiende el grafo que está utilizando.
Escenario D: varios lenguajes
Si el repositorio incluye Java, Go, Rust u otras tecnologías, evalúa el soporte real de cada herramienta y su integración con los sistemas de build existentes. No elijas una herramienta solo por la estructura de carpetas.
8. Riesgos arquitectónicos que ninguna herramienta elimina
Un monorepo puede acabar con dependencias circulares, imports directos a detalles internos y librerías compartidas que se convierten en un punto de acoplamiento excesivo.
Buenas prácticas:
- Definir responsabilidades para cada aplicación y librería.
- Declarar dependencias explícitas.
- Evitar ciclos entre paquetes.
- Mantener APIs públicas claras en las librerías compartidas.
- Separar código reutilizable del código específico de una aplicación.
- Definir qué tareas deben ejecutarse en cada cambio.
- Configurar correctamente entradas y salidas de tareas cacheables.
- Mantener independientes los despliegues cuando sea necesario.
- Acordar propietarios, permisos y reglas de publicación.
Un monorepo no significa un único despliegue, una única base de datos ni una sola aplicación. Es una decisión sobre cómo organizar y evolucionar el código fuente.
9. Estructura de referencia
Para una plataforma con varias aplicaciones y paquetes compartidos:
repo/
├── apps/
│ ├── web/
│ ├── api/
│ └── admin/
├── packages/
│ ├── ui/
│ ├── contracts/
│ ├── config/
│ └── utils/
├── package.json
├── pnpm-workspace.yaml
├── nx.json
└── tsconfig.base.json
Esta estructura es una convención, no un requisito. Lo importante es que las dependencias estén declaradas y que los comandos de build, test y lint sean reproducibles.
En un repositorio pequeño puedes omitir nx.json y comenzar solo con workspaces. Si más adelante necesitas orquestación, Nx puede incorporarse sin exigir que reorganices todo desde cero.
10. Decisión final
Elige Bun Workspaces si ya utilizas Bun y quieres gestionar paquetes locales con poca configuración.
Elige pnpm Workspaces si buscas una base sólida para un monorepo JavaScript/TypeScript, con dependencias explícitas y filtros útiles.
Añade Nx si necesitas entender dependencias entre proyectos, ejecutar solo tareas afectadas y aprovechar caché local o remota.
Una estrategia razonable es comenzar con workspaces y añadir Nx cuando el coste de CI y la coordinación de tareas lo justifiquen. Para repositorios grandes desde el inicio, puede tener sentido incorporar Nx antes si sus capacidades responden a necesidades concretas.
Conclusión
El monorepo resuelve un problema de organización del código. Los workspaces resuelven la gestión de paquetes relacionados. Nx aborda otro problema: coordinar proyectos y tareas de manera inteligente.
Confundir estas capas lleva a elegir herramientas por popularidad o a esperar de un gestor de paquetes capacidades de orquestación que no pretende ofrecer.
La mejor arquitectura no es la que tiene más herramientas, sino la que mantiene las dependencias claras, evita trabajo innecesario y sigue siendo comprensible para el equipo.
Empieza con lo que necesitas hoy, mide dónde aparecen los costes y añade complejidad cuando exista un beneficio concreto.
En esta serie
- Monorepo: Bun, pnpm y Nx (esta nota)
- Deploys en monorepos
Lecturas relacionadas
- Bun: ¿realmente es más rápido que Node.js?
- Node.js vs Bun vs Deno
- Herramienta: qué runtime te conviene