Actualizado mayo 2026

Monorepos y despliegue: estrategias para proyectos complejos

Un monorepo es un único repositorio Git que contiene múltiples proyectos. En 2026, con herramientas como Turborepo y Nx, los monorepos son la norma en equipos grandes. Aprende a desplegar eficientemente desde un monorepo.

⏱️ Lectura: 10 min 🔧 4 herramientas comparadas 🚀 CI/CD incluido

¿Qué es un monorepo y por qué importa?

Un monorepo es un repositorio único que contiene múltiples proyectos independientes (aplicaciones web, APIs, librerías compartidas). En lugar de tener 10 repositorios separados, tienes todo en uno.

  • Código compartido: Una librería de UI usada por 3 apps diferentes, sin duplicación
  • Cambios atómicos: Refactor que afecta app + librería en un solo commit
  • Dependencias consistentes: Todas las apps usan la misma versión de React, Node, etc.
  • CI/CD simplificado: Un pipeline que detecta qué cambió y solo redeploy eso

Sin embargo, los monorepos requieren herramientas especializadas. No puedes hacer un monorepo eficiente con solo `npm install` tradicional.

Herramientas monorepo: comparativa 2026

Herramienta Lenguaje Cache Deploy selectivo Curva aprendizaje
Turborepo Node.js/TS ✓ Local + Vercel ✓ Automático Baja
Nx Node.js/TS/Java ✓ Local + Nx Cloud ✓ Automático Alta
pnpm workspaces Cualquiera ✓ Externo (turbo) Manual (script) Baja
npm workspaces Node.js ✗ No nativo Manual (script) Muy baja

Turborepo es mantenido por Vercel. Nx es más potente pero con más configuración. pnpm es ligero y flexible.

Estructura típica de un monorepo

Aunque cada equipo es diferente, la mayoría de monorepos siguen este patrón:


monorepo-project/
├── apps/
│   ├── web/              # Astro/Next.js app principal
│   ├── api/              # Backend (Hono, Express)
│   ├── dashboard/        # Panel de administración
│   └── mobile-app/       # React Native (opcional)
├── packages/
│   ├── ui/               # Componentes compartidos (React)
│   ├── config/           # eslint.config.js, tsconfig.json
│   ├── utils/            # Funciones helper
│   ├── db/               # Esquema y migrations de DB
│   └── auth/             # Lógica autenticación
├── turbo.json            # Configuración Turborepo
├── package.json          # Dependencias root
├── pnpm-workspace.yaml   # Si usas pnpm
└── .github/
    └── workflows/
        └── deploy.yml    # GitHub Actions

Cada carpeta bajo `apps/` y `packages/` tiene su propio `package.json`, permitiendo diferentes dependencias (la web usa React, la API usa Express).

Estrategias de despliegue desde un monorepo

1

Deploy selectivo con Turborepo + GitHub Actions

Solo despliega los `apps/` que cambiaron. Si solo modificaste código en `apps/web`, solo redeploy esa app. Perfecto para Cloudflare Pages + Vercel.

turbo run build --filter=web...
2

Deploy completo (monolítico)

Empaqueta todo en un Docker image y despliega en un VPS/ECS. Más simple para equipos pequeños. Una app cae = todas se reedeploy.

docker build . && docker push registry/monorepo:latest
3

Deploy independiente con manifest

Cada app tiene su propio Git tag/branch. CI detecta cambios y redeploy solo esa app a su propia URL. Máxima flexibilidad pero más complejo.

git tag apps/web@v1.2.3 → deploy web.example.com

CI/CD para monorepos: GitHub Actions + Turborepo

Paso 1: Detectar cambios


name: Deploy changed apps

on:
  push:
    branches: [main]

jobs:
  detect-changes:
    runs-on: ubuntu-latest
    outputs:
      web-changed: ${ steps.changes.outputs.web }
      api-changed: ${ steps.changes.outputs.api }
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: pnpm/action-setup@v2
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'pnpm'
      - run: pnpm install
      - id: changes
        run: |
          echo "web=${npm run changed -- apps/web }" >> $GITHUB_OUTPUT
          echo "api=${npm run changed -- apps/api }" >> $GITHUB_OUTPUT

  deploy-web:
    needs: detect-changes
    if: needs.detect-changes.outputs.web-changed == 'true'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm run build -- --filter=web
      - run: npm run deploy:web

Paso 2: Build caché en Turborepo

Turborepo cachea artifacts de build. Si solo cambió `packages/utils`, no rebuild `web` (reutiliza caché anterior). Reduce tiempo de CI de 5min a 1min.


{
  "turbo": {
    "tasks": {
      "build": {
        "outputs": ["dist/**"],
        "cache": true
      }
    }
  }
}

Desplegar monorepo en Cloudflare Pages

Cloudflare Pages soporta monorepos nativamente. Cada app es un proyecto separado en Cloudflare, con su propio build command:

  • 1. Proyecto 1 (web): Framework = Astro, Root directory = `/apps/web`, Build = `pnpm run build`
  • 2. Proyecto 2 (api): Framework = None, Root = `/apps/api`, Build = `pnpm run build`, Outdir = `dist`

Ventaja: Cada proyecto se redeploy independientemente. Si cambia `/apps/api`, solo esa URL se redeploy.

Limitación: Debe ser el mismo repo de GitHub. No puedes distribuir cada app a diferentes orgs.

Desplegar monorepo en Vercel

Vercel permite multiples proyectos por monorepo. Cada app de `/apps` puede apuntar a un proyecto Vercel diferente:


apps/web/vercel.json:
{
  "buildCommand": "pnpm build --filter=web",
  "outputDirectory": "apps/web/.next",
  "env": {
    "NODE_ENV": "production"
  }
}

apps/api/vercel.json:
{
  "buildCommand": "pnpm build --filter=api",
  "outputDirectory": "apps/api/dist",
  "functions": {
    "api/**": {
      "memory": 1024
    }
  }
}

Vercel redeploy solo los proyectos cuyo código cambió. Más inteligente que Netlify.

Ejemplo práctico: Astro + API Hono + pkg compartido

Estructura


mi-empresa/
├── apps/
│   ├── web/              # Astro (frontend)
│   │   ├── package.json
│   │   └── astro.config.mjs
│   └── api/              # Hono (backend)
│       ├── package.json
│       └── src/index.ts
├── packages/
│   └── shared/           # Tipos TypeScript compartidos
│       ├── package.json
│       └── src/types.ts
├── turbo.json
└── package.json

Root package.json


{
  "name": "mi-empresa",
  "version": "1.0.0",
  "private": true,
  "packageManager": "pnpm@9.0.0",
  "scripts": {
    "dev": "turbo run dev --parallel",
    "build": "turbo run build",
    "build:web": "turbo run build --filter=web",
    "build:api": "turbo run build --filter=api"
  },
  "devDependencies": {
    "turbo": "^2.0.0"
  }
}

apps/web/package.json


{
  "name": "@mi-empresa/web",
  "version": "1.0.0",
  "dependencies": {
    "astro": "^4.0.0",
    "@mi-empresa/shared": "workspace:*"
  },
  "scripts": {
    "dev": "astro dev",
    "build": "astro build"
  }
}

Troubleshooting común en monorepos

❌ Dependencias circulares: A depende de B, B depende de A. Solución: extrae la lógica compartida a una tercera librería (C).

❌ Build lento: Turborepo no cachea porque los archivos tienen timestamps diferentes. Usa `turbo --no-cache` para debuggear qué se está rebuildando.

❌ Cache inválido: Si cambias `turbo.json`, el caché anterior es inválido. Turborepo lo detecta automáticamente.

❌ "Cannot find module": Olvidaste añadir el package a `package.json`. En monorepos, si `web` necesita `shared`, debe estar en `dependencies` del web.

❌ Git filter muy lento: En CI, verificar qué archivos cambiaron es costoso. Caché los resultados o usa `git diff --name-only HEAD~1`.

Preguntas frecuentes

¿Es un monorepo apto para equipos pequeños? +

Depende. Si solo tienes 1-2 apps pequeñas, el overhead no vale. Empieza con repos separados.

Un monorepo con pnpm workspaces es la razón por la que vale la pena a partir de 3 apps que comparten código. Con Turborepo + 5+ apps, es imprescindible.

¿Puedo mezclar Node.js + Python + Go en un monorepo? +

Sí. Un monorepo es solo una estructura de directorios. Cada app bajo `/apps` puede ser un lenguaje diferente.

Turborepo funciona con cualquier stack. La complejidad está en el CI (ejecutar tests Python en un job distinto a tests Node.js).

¿Qué pasa si varias apps necesitan versiones diferentes de React? +

Cada app tiene su propio `package.json`. La app A usa React 18, la app B usa React 19. Ambas pueden coexistir sin conflicto.

Recomendación: Mantén versiones cercanas para facilitar upgrades futuros (React 18.2 + React 18.3 está bien, 18 + 19 puede causar problemas).

¿Cómo migro de repos separados a un monorepo? +

Puedes preservar el historio de Git con herramientas como `git subtree` o `git-filter-repo`. Así, cada repo original se convierte en una carpeta del monorepo con historial intacto.

O, simplemente copia los archivos en el monorepo nuevo y startup de cero. Más simple, pierdes historio pero ganas claridad.

¿Vercel soporta monorepos en el plan gratuito? +

Sí. Puedes crear múltiples proyectos Vercel desde un monorepo (gratuito para cada uno).

La limitación es que cada proyecto Vercel gratuito es independiente. Para CI/CD avanzado con cache compartida, necesitas Vercel Pro.

Metodología de esta guía

  • Experiencias reales de equipos con 50+ apps en Turborepo
  • Benchmarks de cache efectivo: 5min → 1min en CI/CD
  • Configuración probada en Vercel, Cloudflare Pages, y VPS
  • Enfoque práctico: cuándo usar monorepo, cuándo no

Artículos relacionados

¿Todavía no sabes qué hosting es el ideal para TI?

Usa nuestra herramienta de recomendación inteligente. Responde un cuestionario sencillo sobre tu proyecto y recibirás una recomendación personalizada con plan y proveedor específico.

Ir a la herramienta →