Alternativa a Vercel: alojar Next.js sin lock-in
Vercel cobra en USD, escala el coste serverless por petición y te empuja hacia sus primitivas. Para equipos hispanohablantes, la cuenta se pone fea rápido. Cómo ejecutar Next.js fuera.
Vercel es el mejor producto de DX que existe para Next.js. Build automático en cada push, preview deploys con URL única por commit, edge runtime que corre cerca del usuario, ISR funcionando con una línea de configuración, analytics y Web Vitals integrados sin instalar nada. Para quien empieza una aplicación Next.js en solitario, es objetivamente la mejor elección técnica.
La cuenta empieza a doler en tres puntos previsibles. Este post mapea esos puntos con números reales, defiende a Vercel donde acierta y muestra tres rutas de salida — cada una con su trade-off. Al final, un paso a paso de migración técnica y un cálculo concreto de cuánto ahorra un equipo al salir.
Donde Vercel acierta
Vale empezar por la parte difícil de admitir. Vercel resuelve problemas reales que otros proveedores no resuelven con la misma elegancia:
- Zero-config para Next.js. El equipo de Vercel mantiene el framework. Cada nueva release tiene soporte probado en el proveedor antes de volverse GA. No necesitas configurar adapter, runtime, build cache, nada.
- Preview deploys por commit. Cada pull request abre una URL pública aislada con el build de ese commit. Diseñador revisa, PM aprueba, QA prueba — sin levantar staging compartido.
- Edge functions globales. El código corre en más de 30 regiones simultáneamente. Para usuarios en São Paulo, la latencia de cold start es menor que la de muchos servidores dedicados en GRU.
- ISR y SSG out-of-the-box. Página estática con revalidación programada funciona sin configurar CDN externa, sin invalidación manual.
- Analytics y Web Vitals nativos. Sin instalar script de tercero, sin añadir peso al bundle, métricas reales de Core Web Vitals en producción.
Para un solo dev con un SaaS de US$5k MRR, con app pequeña y tráfico controlado, Vercel cuesta US$20/mes y libera al desarrollador para escribir producto. Es la elección correcta. No hay ironía en esa frase.
El problema es lo que pasa después de que el producto crece.
Los tres puntos donde duele
Punto 1 — Coste escalado en USD
El plan Pro cuesta US$20 por desarrollador al mes como piso. Equipo de cinco personas empieza en US$100/mes solo de licencia, antes de cualquier tráfico o compute.
A partir de ahí el coste es por uso. Las funciones serverless cobran por GB-segundo de ejecución más invocación por petición. Tráfico de salida cobra por GB. Vercel KV, Vercel Postgres, Vercel Blob — cada servicio gestionado tiene su tabla de precios, todas en USD.
La consecuencia operacional es factura imprevisible. Tráfico estacional — Black Friday, lanzamiento de feature, mención en prensa — multiplica por diez el coste de ese mes. Para startup con revenue local y coste en dólar, el spread de margen desaparece primero. Para agencia que cobra al cliente en local y paga infra en dólar, el margen desaparece después.
Punto 2 — Lock-in de primitivas
Este es el punto que nadie ve hasta que necesita salir.
ISR (Incremental Static Regeneration) es una feature de Next.js, pero la implementación optimizada de Vercel usa CDN propietaria con invalidación de tag global. Auto-hospedado, ISR funciona localmente — cada nodo tiene su copia de la caché en disco. Para invalidar una tag en tres nodos necesitas orquestación explícita.
Edge runtime usa primitivas al estilo CloudFlare Workers — fetch global, sin acceso a fs, sin módulos Node nativos. Código escrito para edge no corre directamente en Node tradicional sin refactor.
Image Optimization corre en la infra de Vercel. Le mandas <Image src="/foo.jpg" /> y el proveedor entrega WebP redimensionado, con caché global. Auto-hospedado, necesitas correr sharp en el build, o usar un proxy de imagen dedicado, o desactivar la feature.
Vercel KV, Postgres y Blob son wrappers de Upstash Redis, Neon Postgres y almacenamiento S3-compatible con SDK propio. Migrar de @vercel/kv a ioredis directo es una tarde de refactor. Migrar de @vercel/postgres a cliente estándar es otra tarde. Migrar de @vercel/blob a S3 implica revisar cada upload en la app.
Ninguna de esas barreras es infranqueable. Pero salir de Vercel no es git remote set-url seguido de vercel logout. Es un sprint de refactor para una app de tamaño medio.
Punto 3 — Bandwidth y funciones fuera de control
Vercel no tiene cap rígido por defecto en el plan Pro. Defines alertas de presupuesto, pero la aplicación sigue sirviendo hasta alcanzar el límite — y el límite es configurable hacia arriba, no hacia abajo.
Los tres escenarios malos son previsibles:
- DDoS leve. Mil peticiones por segundo durante una hora golpean en volumen de bandwidth e invocación que rutinariamente pasa de US$200 en un plan normal. Vercel tiene protección contra ataques masivos, pero el umbral para activar la defensa es alto.
- Post viral. Tu página entra en Hacker News o el front de Reddit, y quinientas mil personas acceden en un día. El coste cae sobre ti, no sobre el anunciante.
- Bug en loop. Función en producción con
setIntervalque olvidaste limpiar, o ruta que se llama a sí misma recursivamente en SSR — descubierto en la factura.
Descubres el destrozo cuando llega la tarjeta. El camino de recurso existe, pero es caso a caso y depende de la buena voluntad del proveedor. No es una garantía contractual de techo.
Las tres rutas de salida
Salir de Vercel no significa saltar a Kubernetes. Hay un espectro, y cada peldaño cambia una cosa por otra.
Ruta A — Hospedado, más previsible
Render, Railway y Fly.io ocupan esa franja. Sigues pagando por instancia en USD, sigues confiando en el proveedor para disponibilidad, sigues teniendo panel web y CI/CD integrado. La diferencia es el modelo de cobro.
Render. Precio fijo por instancia al mes. Web service básico US$7/mes, instancia mayor US$25-85/mes. Latencia decente para São Paulo vía Render-Cloud en la región este de EE.UU. Tiene free tier limitado para proyectos personales. Soporte para Next.js standalone directo, sin adapter custom.
Railway. Modelo por uso (CPU + memoria + bandwidth) con cap configurable. Precio previsible porque defines el techo. Buena para MVP corriendo barato, escala hacia arriba cuando lo necesita. UX de consola es excelente.
Fly.io. Multi-region edge sin cobro separado por función. Subes la aplicación y corre en N regiones con el mismo precio. Para app que necesita presencia global pero no quiere pagar tabla de función, es la elección más obvia.
Trade-off de la Ruta A: sigues pagando en USD, sigues dependiendo de un único proveedor para disponibilidad, sigues teniendo que aceptar su tabla de precios cuando cambia. Pero saliste del modelo serverless-por-invocación y ganaste previsibilidad de coste. Para muchos equipos, es suficiente.
Ruta B — Auto-hospedado simple
Los paneles de orquestación modernos se volvieron categoría en los últimos dos años. Coolify, Dokploy, Kamal — cada uno con su filosofía, todos compartiendo el mismo modelo: instala panel en un servidor único, conecta repositorio, despliega aplicación.
Los números cambian de régimen en esa ruta. Un servidor cloud en Hetzner cuesta alrededor de €5/mes. Ese servidor único aloja cómodamente cinco aplicaciones Next.js de tamaño medio, más una base Postgres pequeña, más un Redis. La DX baja a "instala panel, conecta repo, elige dominio, despliega". No tiene build cache global, no tiene preview deploy automático en cada commit (depende de configuración extra), no tiene edge global.
El detalle técnico que hace viable la ruta es el build standalone de Next.js. Añadiendo output: 'standalone' en next.config.js, el build genera un servidor Node compacto con todas las dependencias necesarias copiadas dentro. La imagen Docker resultante queda alrededor de 150 MB. Cada instancia de la aplicación consume aproximadamente 100 MB de RAM en idle, escalando según tráfico. Cinco apps Next.js en un servidor de 4 GB sobra memoria.
Trade-off de la Ruta B: pierdes edge global. Usuario en Tokio accediendo a tu app en SP va a sentir latencia. Pierdes preview deploy automático por commit (necesita configurarse manualmente, o usar panel que lo soporte). Ganas previsibilidad total de coste: la factura del servidor es la misma todos los meses, independiente del tráfico.
Para equipo con clientes locales, la pérdida de edge global es, en la práctica, irrelevante. Latencia São Paulo → São Paulo es menor que latencia São Paulo → Vercel-edge-São Paulo, en la mayoría de las mediciones.
Ruta C — Auto-hospedado con alta disponibilidad
Aquí vive HeroCtl. La diferencia con la Ruta B es el tipo de garantía que puedes dar al cliente.
Los paneles auto-hospedados simples son, por construcción, single-server. Cuando ese servidor cae, el cliente cae con él. Para app personal o MVP, es aceptable. Para contrato B2B con SLA escrito, no lo es.
La Ruta C elimina ese punto único de falla colocando 3 o 4 servidores en un mismo cluster, con plano de control replicado entre ellos. Si un servidor muere, los otros siguen sirviendo — y el cluster reagenda automáticamente los contenedores que estaban en el nodo muerto a otros nodos saludables. La elección de nuevo coordinador toma cerca de 7 segundos después de un kill -9 en el servidor que estaba liderando.
Router integrado emite certificados Let's Encrypt automáticamente, hace rolling update sin ventana de mantenimiento, hace health check en cada contenedor. No montas cinco productos para tener ingress + TLS + métricas + logs — viene todo en el mismo binario.
La franja de aplicación es específica: cuando la startup necesita SLA escrito de cliente (generalmente por encima de US$10k MRR o en contrato B2B serio), la Ruta B empieza a quedar arriesgada. Un único servidor, incluso confiable, es una narrativa difícil de defender cuando el cliente pregunta "¿y si ese servidor cae?". La Ruta C resuelve eso sin volverse Kubernetes.
Lado a lado
La tabla es la versión honesta de la decisión. No hay columna sin matiz.
| Criterio | Vercel | Render | Railway | Coolify | HeroCtl |
|---|---|---|---|---|---|
| Coste mínimo USD/mes | ~US$20/dev | ~US$7 | ~US$5 | ~US$6 (1 VPS) | ~US$24 (3-4 VPS) |
| Coste previsible | No | Sí | Sí (con cap) | Sí | Sí |
| Edge global | Sí (30+ regiones) | No | No | No | No |
| ISR Next.js | Nativo, optimizado | Funciona local | Funciona local | Funciona local | Funciona local |
| Image Optimization | Hospedado | Build/proxy | Build/proxy | Build/proxy | Build/proxy |
| Preview deploys | Automático por commit | Manual/branch | Manual/branch | Manual | Manual |
| TLS automático | Sí | Sí | Sí | Sí | Sí |
| Multi-region | Sí | Limitado | Limitado | No | Configurable |
| SLA contractual | 99,99% (Enterprise) | 99,95% | 99,9% | Best-effort | Configurable (tú operas) |
| Alta disponibilidad real | Sí | Sí | Sí | No | Sí |
| Soporte en español | No | No | No | Comunidad | Sí (Business) |
| Lock-in de primitivas | Alto (KV/Postgres/Blob/Edge) | Bajo | Bajo | Ninguno | Ninguno |
La columna que importa cambia según la etapa. Solo dev mira la primera línea. Equipo creciendo mira "coste previsible". Startup con cliente B2B mira "SLA contractual" y "alta disponibilidad real".
Cuándo quedarse en Vercel
La honestidad es el mecanismo de defensa de cualquier comparativa. Cuatro escenarios donde salir es perjuicio:
Solo dev haciendo SaaS pequeño en USD con revenue saludable. Si la aplicación ya cobra en dólar y el revenue pasa de US$30k MRR, US$100-300/mes de Vercel es ruido contable. El tiempo gastado migrando vale más que el ahorro.
Marketing site Next.js de baja complejidad. Página estática con formulario de contacto. Vercel hace eso gratis en el plan Hobby, y el tier gratuito no tiene límite duro para ese perfil de tráfico. Cambiar a auto-hospedado es mover el problema en lugar de resolverlo.
Equipo pequeño sin nadie para cuidar de infra, con revenue justificándolo. Vercel es, en el fondo, tercerización de operación. Si tu margen soporta el precio, y tu único dev sénior necesita estar escribiendo producto, mantener Vercel es decisión de asignación de tiempo, no de tecnología.
Edge global crítico para UX. Aplicación con usuarios en tres continentes donde latencia por debajo de 50ms globalmente es parte del producto. Auto-hospedado con presencia global es caro y operacionalmente complicado. Vercel resuelve.
Si estás en cualquiera de esos cuatro perfiles, cierra esta pestaña y vuelve al código. El resto del post no es para ti todavía.
Migración técnica de Vercel a auto-hospedado
Para quien decidió salir, el camino tiene siete pasos. Cada uno toma entre una tarde y dos días, dependiendo del tamaño de la app.
1. Inventario
Antes de mover cualquier cosa, mapea lo que está en uso. Lista de variables de entorno del proyecto Vercel — copia todo en un archivo .env.example versionado. Lista de dependencias Vercel-only que aparecen en package.json: @vercel/kv, @vercel/postgres, @vercel/blob, @vercel/analytics, @vercel/speed-insights. Lista de features Next.js que dependen de runtime específico: ISR (busca por revalidate en el código), middleware (¿existe middleware.ts en la raíz?), edge runtime (export const runtime = 'edge'), Image Optimization (<Image /> en cuántas rutas?).
El inventario no cambia nada. Pero decide el orden de los siguientes pasos.
2. Build standalone
Añade output: 'standalone' en next.config.js. Ese modo hace que el build copie a .next/standalone/ solo las dependencias de producción realmente usadas, más un servidor Node mínimo (server.js).
// next.config.js
module.exports = {
output: 'standalone',
// demás opciones
}
Build local con next build produce una carpeta de unos 150 MB. Dockerfile queda corto:
FROM node:20-alpine AS builder
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN corepack enable && pnpm install --frozen-lockfile
COPY . .
RUN pnpm build
FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
COPY --from=builder /app/public ./public
EXPOSE 3000
CMD ["node", "server.js"]
Imagen final alrededor de 180 MB. Corre igual en cualquier entorno que soporte contenedor.
3. Sustitución de almacenamiento
Cada servicio gestionado de Vercel tiene alternativa directa:
- Vercel KV → Redis. Levantas un Redis en el cluster (HeroCtl lo corre como job común) o usas Upstash hospedado. Cliente cambia de
@vercel/kvaioredis. La API es parecida; el adapter se puede esconder detrás de una función. - Vercel Postgres → Postgres. Postgres en el cluster (job común) o Supabase/Neon hospedados. Migration scripts siguen iguales. Cliente cambia de
@vercel/postgresapgopostgres.js. - Vercel Blob → S3-compatible. CloudFlare R2 (sin cobro de salida), Backblaze B2, o MinIO en el propio cluster. Cliente cambia de
@vercel/bloba@aws-sdk/client-s3apuntando al endpoint custom.
La regla general: haz la sustitución en una rama separada, con tests de integración corriendo contra el servicio nuevo, antes de tocar producción.
4. Image Optimization
Tres caminos, elige uno:
sharpdirecto en el servidor. Next.js detectasharpinstalado y lo usa para Image Optimization local. Funciona, pero consume CPU del mismo proceso que sirve la aplicación.next-image-export-optimizer. Pre-optimiza todas las imágenes en el build. Bueno para blog o site con imágenes estáticas. Inviable para app con upload de usuario.- Proxy de imagen dedicado.
imgproxyoimageflowcorriendo como servicio separado. URL del<Image />apunta a ese proxy. Resuelve cualquier caso de uso, cuesta un job más en el cluster.
5. ISR
Auto-hospedado, ISR funciona — Next.js standalone implementa la caché local en disco. El punto frágil es la invalidación multi-region.
Cluster con 3 nodos significa 3 copias de la caché en disco, cada una con expiración propia. Para blog o site cuyo contenido cambia algunas veces al día, eso es aceptable: la inconsistencia de algunos segundos entre nodos es invisible para el usuario. Para dashboard de e-commerce con precio actualizando cada minuto, necesitas invalidación coordinada — generalmente vía webhook que llama revalidatePath en todos los nodos simultáneamente.
La mayoría de los casos cae en el primer perfil. No se vuelve el problema que parece a primera vista.
6. CI/CD
Cambiar el auto-deploy de Vercel por pipeline propio:
- Build: GitHub Actions (o GitLab CI, o Jenkins) corre en cada push.
pnpm install,pnpm build, genera imagen Docker. - Push: registry de imagen (ECR, Docker Hub, GHCR). Tag por commit SHA o fecha.
- Deploy: llamada de API contra el orquestrador (
heroctl deploy job.jsono equivalente). Rolling update sin downtime.
Tiempo de pipeline para app medio queda alrededor de 4-6 minutos. Vercel lo hace en 2-3 minutos. La diferencia es real, pero no es catastrófica.
7. Cutover
Última etapa, y la más delicada:
- Sube la versión auto-hospedada apuntando a un dominio temporal (
new.tuapp.com, por ejemplo). - Corre en paralelo durante 7 días. Usuarios internos prueban. Tráfico de canario dirigido por flag.
- Compara métricas: error rate, latencia p95, coste de infra proyectado.
- Si la parity está ok, cambia DNS principal para apuntar al nuevo backend. TTL bajo (60s) ayuda en el rollback rápido.
- Mantén Vercel encendido por otros 7 días. Solo desactiva el proyecto después de confirmar que nadie está en el DNS antiguo.
Migración total para app medio toma 2-3 semanas con un dev dedicado. Para app pequeño, una semana. Para monolito Next.js gigante con 50 rutas y middleware complejo, un trimestre.
Cálculo concreto
Números para cerrar el argumento. Equipo de cinco devs con aplicación Next.js de tamaño medio (50 rutas, base Postgres, storage de imágenes, tráfico de 2 millones de peticiones/mes).
Escenario Vercel:
- 5 × Pro (US$20/dev/mes) = US$100/mes
- Bandwidth e function invocations (estimación con tráfico informado): US$50-200/mes
- Vercel Postgres (instancia producción pequeña): US$30/mes
- Vercel Blob (50 GB almacenado, 100 GB transferencia): US$20/mes
- Total: US$200-400/mes
Escenario HeroCtl Community en 4 servidores Hetzner:
- 4 × CX22 (€5,18/mes cada uno) = €21/mes
- CloudFlare R2 (50 GB almacenado, sin cobro de salida): ~€5/mes
- Postgres corriendo como job en el propio cluster: cero adicional
- Total: €25-30/mes
Diferencia: ~US$170-370/mes. En 12 meses, US$2.000 a US$4.500 de ahorro. Equivalente a un mes de salario de dev en muchos mercados.
El ahorro paga una migración hecha en cuatro semanas en el primer año, y queda disponible como margen operacional en los siguientes.
Preguntas que recibimos
¿HeroCtl corre Next.js directo? Sí. Build standalone genera imagen Docker, y HeroCtl orquesta cualquier imagen. No tiene adapter custom, no tiene template específico — el Dockerfile mostrado arriba funciona sin modificación.
¿E ISR sin CDN global?
Funciona localmente en cada nodo del cluster. Cluster con 3 nodos significa 3 cachés independientes con expiración propia. Para invalidación coordinada multi-nodo, usas revalidatePath llamado vía webhook en todos los nodos. Para la mayoría de los casos (blog, site institucional, dashboard con revalidación cada minuto), la inconsistencia transitoria es invisible.
¿Cómo hago preview deploys?
HeroCtl no tiene preview deploy automático por commit nativo, pero soporta múltiples versiones del mismo job corriendo lado a lado. Configuración común: pipeline crea un job con sufijo de la rama (mi-app-feature-x), con dominio temporal (feature-x.preview.tuapp.com), TLS automático por el router integrado. Cuando la rama se mergea y se borra, el job se despromueve. Quien quiere DX exacta de Vercel monta eso en 100-200 líneas de pipeline.
¿Sobreviven las edge functions?
Las edge functions usan primitivas al estilo CloudFlare Workers y no corren en Node tradicional. Auto-hospedado, las conviertes en rutas server-side normales (export const runtime = 'nodejs') o las separas en servicios propios. El refactor es por archivo, generalmente entre 10 minutos y 2 horas dependiendo del código.
¿Y si uso Vercel Postgres?@vercel/postgres es wrapper de Neon Postgres. Cambias a @neondatabase/serverless (mantienes Neon hospedado), o pg/postgres.js apuntando a un Postgres en el cluster. Schema migra directo vía pg_dump + pg_restore. Para 95% de las apps, es una tarde de trabajo.
¿Vercel Image Optimization tiene sustituto?
Tres opciones: sharp directo en el servidor (funciona, consume CPU local), next-image-export-optimizer en el build (bueno para imágenes estáticas), proxy dedicado tipo imgproxy corriendo como servicio separado (resuelve cualquier caso). Para app con upload de usuario, la tercera opción es la mejor.
¿Cuánto tarda la migración para app medio? Aplicación Next.js con 50 rutas, Postgres, storage y middleware: 2-3 semanas con un dev dedicado siguiendo el paso a paso de este post. Aplicación pequeña (10-15 rutas, sin storage gestionado): una semana. Monolito gigante con middleware complejo y dependencia fuerte de edge runtime: trimestre entero.
Cierre
Vercel es una buena elección. Para muchos casos, es la elección correcta. El punto de este post no es "Vercel es malo" — es "Vercel no es la única elección". La mayoría de los equipos que miran la factura mensual y suspiran no están mirando hacia afuera porque su producto sea peor. Están mirando porque el ahorro, a escala de empresa, es lo suficientemente grande como para pagar una migración hecha con calma y que sobre caja.
La elección entre las tres rutas depende de dónde estás. Render y Railway resuelven el problema de previsibilidad sin cambiar mucho el modelo operacional. Coolify y Dokploy resuelven el coste radicalmente, a cambio de un único servidor. HeroCtl resuelve el coste y mantiene la alta disponibilidad real, a cambio de operar 3-4 servidores.
Si quieres probar la Ruta C en el camino más corto:
curl -sSL get.heroctl.com/install.sh | sh
Levantas 3 servidores pequeños, instalas en cada uno, apuntas el dominio. Subes la aplicación Next.js como job. Verificas que el router integrado emitió certificado, que el rolling update funcionó, que matar un servidor no derribó el site. Después decides si el ahorro compensa.
Para leer más: Por qué creamos HeroCtl explica la tesis general detrás del producto, y Heroku auto-hospedado en 2026 cubre la franja de uso adyacente — cuándo quieres DX tipo Heroku corriendo en tu infra, sin necesitar el nivel de HA de HeroCtl.
La intención, como siempre, es la misma: orquestación de contenedores, sin ceremonia.