OpenNext: Self-Host Next.js Sin Vercel (AWS, Cloudflare, VPS)
Tu factura de Vercel llega a $847 en marzo—tu sitio Next.js marketing, 40,000 visitas, tres funciones serverless. Abres el desglose de facturación y ves los cargos apilarse: sobrecostos de ancho de banda, invocaciones de funciones, optimización de imágenes. El mismo sitio en AWS con OpenNext cuesta $23/mes. He migrado tres aplicaciones en producción en el último año—una tienda de comercio electrónico facturando $2M anuales, un dashboard SaaS con 8,000 usuarios activos, un portafolio de agencia. Cada migración tomó menos de cuatro horas. Cada una redujo costos de hosting en 91–97%. Las métricas de rendimiento se mantuvieron planas o mejoraron. Pero aquí hay lo que la documentación de OpenNext no te dirá: el primer deploy fallará, tu middleware se romperá de formas sutiles, y pasarás una tarde depurando headers de caché. Este es el manual de migración que desearía haber tenido en enero de 2025 cuando nuestra primera factura superó cuatro dígitos.
Este no es un artículo "Vercel es malo". Vercel es genuinamente excelente. Pero ya no es la única opción, y para muchos equipos, no es la correcta. Déjame guiarte a través de todo lo que he aprendido sobre self-hosting Next.js con OpenNext — lo bueno, lo feo, y lo sorprendentemente asequible.
Tabla de Contenidos
- ¿Qué Es OpenNext y Por Qué Existe
- El Panorama de Self-Hosting en 2026
- Destino de Deployment: AWS con SST
- Destino de Deployment: Cloudflare Workers
- Destino de Deployment: VPS con Docker
- Comparación de Costos: Vercel vs Self-Hosted
- Cuándo Dejar Vercel
- El Manual de Migración
- Errores Comunes y Cómo Evitarlos
- FAQ

¿Qué Es OpenNext y Por Qué Existe
Next.js fue diseñado para ejecutarse en Vercel. Eso no es conspiración — es arquitectura. Características como ISR (Incremental Static Regeneration), middleware, optimización de imágenes, y server actions tienen implementaciones específicas de Vercel incorporadas. Cuando intentas next start en un servidor aleatorio, obtienes un subconjunto de lo que Next.js puede hacer.
OpenNext es un adaptador de código abierto que toma tu salida de compilación de Next.js y la transforma en paquetes de deployment que funcionan en otras plataformas. Comenzó como un proyecto comunitario de SST enfocado en AWS Lambda, pero a partir de v3 (la versión principal actual en 2026), soporta múltiples destinos de deployment incluyendo Cloudflare Workers, servidores Node.js tradicionales, y más.
Aquí está lo que OpenNext realmente maneja:
- ISR y revalidación — El sistema de revalidación basado en tags que Vercel implementa con su infraestructura interna? OpenNext lo recrea usando DynamoDB + SQS en AWS, o KV stores en Cloudflare.
- Optimización de imágenes — El componente
<Image>de Next.js depende de una API de optimización. OpenNext empaqueta un optimizador basado en Sharp o lo enruta a soluciones específicas de plataforma. - Middleware — Se ejecuta en el edge en Vercel. OpenNext lo mapea a CloudFront Functions, Cloudflare Workers, o lo ejecuta en-process en VPS.
- Server actions — Soporte completo, enrutado a través de la función de servidor apropiada.
- Streaming y partial prerendering — El soporte ha madurado significativamente en OpenNext v3.x.
Lo Que OpenNext No Es
No es una plataforma de hosting. No es un CDN. Es un adaptador de compilación — una capa de traducción entre la salida de Next.js y tu infraestructura. Aún necesitas ejecutar la cosa en algún lugar.
El Panorama de Self-Hosting en 2026
El ecosistema ha explotado desde que comencé a mirar esto. Aquí está dónde están las cosas:
| Plataforma | Soporte OpenNext | Madurez | Mejor Para |
|---|---|---|---|
| AWS (vía SST) | Primera clase | Listo para producción | Equipos ya en AWS |
| Cloudflare Workers | Adaptador oficial | Estable (algunos casos edge) | Apps edge-first, optimización de costos |
| Docker/VPS | Comunidad + oficial | Estable | Deployments simples, infra existente |
| Kubernetes | Helm charts comunitarios | Madurando | Enterprise, clusters K8s existentes |
| Netlify | Built-in (adaptador propio) | Listo para producción | Equipos comprometidos con Netlify |
| Google Cloud Run | Comunidad | Experimental | Tiendas GCP |
Los dos caminos que he probado personalmente en batalla y puedo avalar son AWS vía SST y Docker en VPS. Cloudflare es el recién llegado emocionante que está mejorando mensualmente.
Destino de Deployment: AWS con SST
Este es el camino dorado. SST (Serverless Stack) tiene soporte Next.js incorporado powered by OpenNext, y es donde ha ido la mayoría del esfuerzo de ingeniería.
Descripción General de la Arquitectura
Cuando despliega Next.js vía SST en AWS, aquí está lo que se crea:
- Distribución CloudFront — Tu CDN, maneja activos estáticos y enrutamiento
- Función(es) Lambda — Server-side rendering, rutas API, server actions
- Bucket S3 — Activos estáticos, páginas pre-renderizadas, caché ISR
- Tabla DynamoDB — Mapeo de tags ISR para revalidación
- Cola SQS — Procesamiento de revalidación asincrónica
- CloudFront Function o Lambda@Edge — Ejecución de middleware
Parece mucho. Lo es. Pero SST abstrae todo en aproximadamente 20 líneas de config.
Configuración SST
Aquí hay un real sst.config.ts de uno de mis proyectos en producción:
/// <reference path="./.sst/platform/config.d.ts" />
export default $config({
app(input) {
return {
name: "my-nextjs-app",
removal: input.stage === "production" ? "retain" : "remove",
home: "aws",
providers: {
aws: {
region: "us-east-1",
},
},
};
},
async run() {
const site = new sst.aws.Nextjs("Site", {
domain: {
name: "myapp.com",
dns: sst.aws.dns(),
},
warm: 5, // mantener 5 instancias Lambda calientes
memory: "1024 MB",
environment: {
DATABASE_URL: process.env.DATABASE_URL!,
NEXT_PUBLIC_API_URL: "https://api.myapp.com",
},
});
return {
url: site.url,
};
},
});
Luego despliega:
npx sst deploy --stage production
El primer deployment toma 8-12 minutos (propagación de distribución CloudFront). Los deployments posteriores toman 2-4 minutos.
Consideraciones de Lambda
El mayor gotcha con hosting basado en Lambda son los cold starts. Las funciones de servidor de Next.js no son pequeñas — estamos hablando de bundles de 20-80MB dependiendo de tus dependencias. Los cold starts varían de 800ms a 3 segundos.
Mitigaciones que he usado:
- Provisioned concurrency — El parámetro
warmde SST mantiene instancias calientes. A $0.0000041667 por GB-segundo, mantener 5 instancias de una función de 1GB caliente cuesta ~$15/mes. - Bundles más pequeños — Audita tus dependencias del lado del servidor. Encontré un proyecto importando
lodashdel lado del servidor cuando solo necesitábamoslodash/get. El bundle se redujo de 68MB a 31MB. - Deployment regional — No uses Lambda@Edge para SSR a menos que absolutamente lo necesites. Lambda de región única con caché CloudFront está bien para el 95% de las apps.

Destino de Deployment: Cloudflare Workers
Cloudflare ha estado haciendo movimientos serios. Su runtime de Workers ahora soporta suficientes APIs de Node.js para que Next.js realmente pueda ejecutarse allí, y el adaptador de OpenNext para Cloudflare se ha vuelto notablemente estable.
Setup con OpenNext Cloudflare
npm install @opennext/cloudflare
Agrega a tu wrangler.toml:
name = "my-nextjs-app"
main = ".open-next/worker.js"
compatibility_date = "2025-01-01"
compatibility_flags = ["nodejs_compat_v2"]
[assets]
directory = ".open-next/assets"
binding = "ASSETS"
[[kv_namespaces]]
binding = "NEXT_CACHE_KV"
id = "your-kv-namespace-id"
Compila y despliega:
npx @opennext/cloudflare build
npx wrangler deploy
Los Compromisos de Cloudflare
Pros:
- Sin cold starts — Los Workers se inician en menos de 5ms globalmente
- Edge global por defecto — Tu SSR se ejecuta en 300+ ubicaciones
- Precios absurdos — $5/mes para 10 millones de requests en el plan pagado
Contras:
- Límites de memoria — 128MB en free, 256MB en pagado. Las apps grandes de Next.js pueden alcanzar esto.
- Límites de tiempo de CPU — 30 segundos en plan pagado. Las páginas SSR pesadas pueden ser un problema.
- Brechas de compatibilidad Node.js — La mayoría de cosas funcionan, pero si estás usando módulos nativos de Node como
sharpdirectamente, necesitarás workarounds. Cloudflare Images puede manejar optimización en su lugar. - Algunas características de Next.js no son soportadas — A partir de principios de 2026, el soporte de partial prerendering aún es experimental en Cloudflare.
Para sitios con mucho contenido y páginas marketing, Cloudflare Workers es increíblemente convincente. Para aplicaciones web complejas con lógica pesada del lado del servidor, seguiría inclinándome hacia AWS o Docker.
Destino de Deployment: VPS con Docker
A veces solo quieres un servidor. Sin funciones Lambda, sin runtime edge, sin un diagrama de arquitectura de 47 servicios. Una caja que ejecute tu código. Respeto eso.
El Dockerfile
Aquí está el Dockerfile de producción que uso. Es multi-stage, optimizado, y realmente funciona:
# Stage 1: Dependencies
FROM node:20-alpine AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN corepack enable pnpm && pnpm install --frozen-lockfile
# Stage 2: Build
FROM node:20-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
ENV NEXT_TELEMETRY_DISABLED=1
ENV NODE_ENV=production
RUN corepack enable pnpm && pnpm build
# Stage 3: Production
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT=3000
ENV HOSTNAME="0.0.0.0"
CMD ["node", "server.js"]
Crítico: necesitas output: 'standalone' en tu next.config.js:
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'standalone',
};
module.exports = nextConfig;
Recomendaciones de VPS
He ejecutado esta configuración en varios proveedores:
| Proveedor | Especificación | Costo Mensual | Notas |
|---|---|---|---|
| Hetzner CAX21 | 4 vCPU ARM, 8GB RAM | €7.49 (~$8) | Mejor valor, datacenters EU |
| DigitalOcean Droplet | 2 vCPU, 4GB RAM | $24 | Buena cobertura US |
| Fly.io (machine) | 2 vCPU, 4GB RAM | ~$30 | Auto-scaling, regiones globales |
| Railway | Basado en uso | $5-50 | Setup más fácil, DX tipo Vercel |
| AWS EC2 t4g.medium | 2 vCPU, 4GB RAM | ~$25 | Ya en AWS |
Para un deployment Docker directo, Hetzner tiene una relación valor-precio absurdamente buena. Ejecuto una app Next.js sirviendo 2M+ pageviews/mes en una instancia ARM de Hetzner €7.49 detrás del tier free de Cloudflare. El servidor apenas suda.
Lo Que Pierdes con Docker/VPS
Seamos honestos sobre lo que next start en VPS no te da comparado con Vercel o la configuración SST:
- Revalidación ISR es básica — Caché del sistema de archivos solamente. Sin caché distribuida entre múltiples instancias. Si estás ejecutando un servidor único, esto está bien. ¿Múltiples servidores? Necesitas Redis o una capa de caché compartida.
- Sin middleware edge — Middleware se ejecuta en-process, lo cual está totalmente bien para la mayoría de casos de uso.
- Optimización de imágenes — Funciona vía Sharp, pero estás sirviendo imágenes optimizadas desde tu origen único. Coloca Cloudflare o un CDN enfrente.
- Sin deployments atómicos — Necesitas manejar deploys sin tiempo de inactividad tú mismo (Docker Compose con health checks, o un reverse proxy como Caddy/Traefik).
Para la mayoría de apps en Social Animal, especialmente los builds de headless CMS que hacemos a través de nuestro trabajo de headless CMS development, una única VPS con un CDN enfrente es perfectamente adecuada.
Comparación de Costos: Vercel vs Self-Hosted
Hablemos dinero. Esto se basa en datos de facturación reales de una app Next.js haciendo ~5M requests/mes con ISR, optimización de imágenes, y server-side rendering moderado.
| Factor de Costo | Vercel Pro | Vercel Enterprise | AWS/SST | Cloudflare | Hetzner VPS |
|---|---|---|---|---|---|
| Plataforma base | $20/usuario/mes | Custom (~$3k+/mes) | $0 | $5/mes | €7.49/mes |
| Compute/requests | $150-400/mes | Incluido | $40-80/mes | $0-15/mes | Incluido |
| Ancho de banda (100GB) | Incluido | Incluido | $8.50 (CloudFront) | Incluido | Incluido |
| Optimización de imágenes | $50-200/mes | Incluido | $5-15/mes (Lambda) | $5/mes (CF Images) | Incluido (Sharp) |
| ISR/Caché | Incluido | Incluido | $2-5/mes (DynamoDB) | $0-5/mes (KV) | $0 |
| Total Estimado | $300-700/mes | $3,000+/mes | $55-110/mes | $10-25/mes | $8-15/mes |
Esos números de Vercel no son hipotéticos. He visto las facturas. Los precios por asiento, cargos por sobrecosto de ejecución de función, y cargos de ancho de banda en tier Pro se suman rápido para equipos de 5+.
Los números AWS/SST asumen tráfico moderado con provisioned concurrency. El precio de Cloudflare es genuinamente salvaje — es difícil gastar dinero real allí a menos que estés haciendo algo exótico.
Cuándo Dejar Vercel
No dejes solo porque puedas. Déjalo porque debes. Aquí está mi marco:
Permanece en Vercel si:
- Tu equipo es pequeño (1-3 devs) y el tiempo del desarrollador es tu recurso más caro
- Estás gastando menos de $100/mes en Vercel
- No tienes a nadie que disfrute el trabajo de infraestructura
- Estás iterando rápido y necesitas previsualizaciones instantáneas para cada PR
- Estás usando características específicas de Vercel como Analytics, Speed Insights, o integraciones de Vercel AI SDK
Déjalo si:
- La factura mensual supera $500 y está creciendo
- Necesitas infraestructura en regiones específicas para compliance (GDPR, residencia de datos)
- Ya estás ejecutando infraestructura significativa de AWS/GCP/Cloudflare
- Los cold starts en serverless son inaceptables para tu caso de uso
- Necesitas estrategias de caché personalizadas que no encajan en el modelo de Vercel
- Has golpeado los límites de tamaño de función o tiempo de ejecución de Vercel
Considera seriamente dejarlo si:
- Estás en precios de Vercel Enterprise y el renovación de contrato acaba de llegar
- Tu app es mayormente estática/ISR y estás pagando precios SSR dinámico
- Quieres ejecutar tu frontend junto a tu backend en la misma infraestructura
El Manual de Migración
He hecho esto tres veces ahora. Aquí está el proceso que sigo, refinado a través de experiencia dolorosa.
Paso 1: Audita Tus Características de Next.js
Antes de que toques nada, cataloga qué características de Next.js realmente usas:
# Encontrar middleware
find . -name "middleware.ts" -o -name "middleware.js"
# Encontrar rutas API
find ./app -name "route.ts" -o -name "route.js" | head -20
# Verificar ISR
grep -r "revalidate" ./app --include="*.ts" --include="*.tsx" | head -20
# Verificar server actions
grep -r "use server" ./app --include="*.ts" --include="*.tsx" | head -20
# Verificar next.config para características especiales
cat next.config.js
Paso 2: Elige Tu Destino
Basado en la auditoría:
- ISR pesado + middleware + optimización de imágenes → AWS/SST
- SSR simple + sitio de contenido → Cloudflare o VPS
- Ya tienes infraestructura Docker/K8s → VPS/Docker
- Necesitarlo listo para el viernes → Docker en Railway o Fly.io
Si estás construyendo con Next.js o Astro, la elección de plataforma de destino impacta significativamente tus decisiones de arquitectura.
Paso 3: Configura CI/CD
El CI/CD de Vercel es genuinamente excelente. Lo vas a extrañar. Reprodúcelo con GitHub Actions:
# .github/workflows/deploy.yml
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 9
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'pnpm'
- run: pnpm install --frozen-lockfile
- run: pnpm build
- run: pnpm test
# Para SST:
- run: npx sst deploy --stage production
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
# Para Docker/VPS (alternativa):
# - run: docker build -t myapp .
# - run: docker push registry.example.com/myapp:latest
# - run: ssh deploy@server 'cd /app && docker compose pull && docker compose up -d'
Paso 4: Deployments de Preview
Esta es la una cosa que la gente extraña más de Vercel. Para SST, usa stages:
# En tu workflow de CI de PR
npx sst deploy --stage pr-${{ github.event.pull_request.number }}
Para Docker, herramientas como Coolify (self-hosted) o Railway manejan bien deployments de preview.
Paso 5: Cutover de DNS
El momento actual de la migración. Siempre recomiendo:
- Desplegar a nueva infraestructura junto a Vercel
- Probar a fondo con un dominio de staging
- Baja TTL de DNS a 60 segundos un día antes
- Corta DNS durante horas de bajo tráfico
- Mantén deployment de Vercel ejecutándose por 48 horas como fallback
- Monitorea tasas de error, TTFB, y Core Web Vitals de cerca
Paso 6: Deriba Vercel
Una vez que estés confiado (dale al menos una semana), cancela la suscripción de Vercel y elimina el proyecto. No dejes proyectos zombis acumulando cargos.
Errores Comunes y Cómo Evitarlos
Variables de entorno desaparecen. Next.js tiene vars con prefijo NEXT_PUBLIC_ (empaquetadas en tiempo de compilación) y vars solo de servidor (disponibles en runtime). En Vercel, esta distinción es algo borrosa. En self-hosted, es estricta. Asegúrate de que todas las vars NEXT_PUBLIC_ estén disponibles en tiempo de compilación en tu CI.
Caché ISR no persiste. En Docker, el directorio .next/cache necesita estar en un volumen persistente. De lo contrario, cada reinicio de contenedor pierde tus páginas en caché:
# docker-compose.yml
services:
web:
build: .
ports:
- "3000:3000"
volumes:
- next-cache:/app/.next/cache
volumes:
next-cache:
Fallos de instalación de Sharp. La biblioteca de optimización de imágenes sharp necesita binarios específicos de plataforma. En Docker, asegúrate de instalar dependencias dentro de la misma arquitectura que tu runtime. El Dockerfile anterior maneja esto usando builds multi-stage con la misma imagen base.
Diferencias de comportamiento de Middleware. Vercel ejecuta middleware en su red edge. En AWS/SST, se ejecuta como CloudFront Function (limitado a ejecución de 10ms, tamaño 2MB). El middleware complejo podría necesitar ser movido a la función de servidor. He tenido que refactorizar middleware de auth por estos límites.
Headers y rewrites faltantes. Si estabas confiando en vercel.json para headers, redirecciones, o rewrites, necesitas mover estos a next.config.js o tu configuración de CDN/reverse proxy.
Si todo esto se siente abrumador, ese es exactamente el tipo de trabajo de infraestructura que hacemos en Social Animal. Revisa nuestro pricing o ponte en contacto — hemos hecho suficientes migraciones para tener un proceso refinado.
FAQ
¿Está OpenNext listo para producción en 2026?
Sí. OpenNext v3.x está ejecutando cargas de trabajo de producción para miles de compañías. El camino SST/AWS es el más probado en batalla, con soporte de Cloudflare cerca. No llamaría soporte de Google Cloud o Kubernetes puro maduro aún, pero AWS y Cloudflare son sólidos.
¿OpenNext soporta Next.js App Router y Server Components?
Soporte completo. App Router, Server Components, Server Actions, streaming, y Suspense funcionan todos. El equipo de OpenNext rastrea las versiones de Next.js de cerca, aunque típicamente hay un lag de 1-3 semanas después de versiones principales de Next.js antes de que OpenNext alcance.
¿Cuánto realmente puedo ahorrar dejando Vercel?
Depende mucho de tus patrones de uso. Para un equipo de 5 desarrolladores ejecutando una app de tráfico moderado, he visto equipos ir de $600-800/mes en Vercel Pro a $30-80/mes en AWS/SST o bajo $20/mes en VPS. Los ahorros son reales pero también lo es la carga de mantenimiento adicional.
¿Puedo usar ISR (Incremental Static Regeneration) sin Vercel?
Absolutamente. En AWS/SST, ISR usa DynamoDB para el caché de tags y SQS para revalidación asincrónica — es totalmente funcional incluyendo revalidación on-demand vía revalidateTag() y revalidatePath(). En VPS, ISR funciona con caché del sistema de archivos, lo cual está bien para deployments de servidor único.
¿Qué hay sobre los deployments de preview de Vercel? ¿Puedo replicar esos?
Puedes obtener el 80% de la experiencia. SST soporta deployments basados en stages, así que cada PR puede obtener su propio stack. Coolify y herramientas similares ofrecen deployments de preview para setups basados en Docker. Lo que no fácilmente replicarás es el sistema de comentarios visuales de Vercel y la integración apretada de GitHub para estado de deployment. La mayoría de equipos encuentran el tradeoff aceptable.
¿Debería usar OpenNext con Cloudflare o AWS para un sitio de headless CMS?
Para sitios de headless CMS ricos en contenido (Sanity, Contentful, Storyblok), Cloudflare Workers es una opción excelente. Estos sitios tienden a ser ISR-pesados con lógica del lado del servidor relativamente ligera — perfecto para el modelo de precios de Cloudflare. Solo iría AWS si necesitas características que Cloudflare aún no soporta o si ya estás profundamente en el ecosistema AWS.
¿Es auto-hostear Next.js más difícil que auto-hostear Astro o Remix?
Honestamente? Sí. Next.js tiene la salida de compilación más compleja de cualquier framework por características como ISR, middleware, optimización de imágenes, y partial prerendering. Astro y Remix tienen historias de deployment mucho más simples. Si estás iniciando un nuevo proyecto y el auto-hosting es una prioridad, considera Astro — es dramáticamente más simple de hostear. Pero si ya estás en Next.js, OpenNext hace la migración práctica.
¿Qué sucede si OpenNext deja de ser mantenido?
OpenNext es respaldado por SST y tiene una comunidad activa con patrocinadores principales. Dicho esto, esta es una preocupación legítima para cualquier dependencia de código abierto. La mitigación es que el enfoque Docker/standalone (next start) funciona sin OpenNext en absoluto — solo pierdes algunas características más avanzadas como revalidación de tags ISR y middleware edge. Es una degradación graciosa, no un acantilado.