Desplegar Next.js en Vercel es la vía de menor fricción que existe: conectas el repo, haces git push y en segundos tienes preview deployments, HTTPS, CDN global e ISR funcionando sin tocar infraestructura. El problema no es arrancar, es lo que pasa cuando el proyecto crece: la factura empieza a moverse y no siempre entiendes por qué. Aquí van los costes reales de 2026, dónde están las sorpresas y cómo exprimir el rendimiento sin dispararlos.
El plan Hobby es gratis pero solo para proyectos no comerciales. En cuanto tu proyecto genera ingresos, Vercel te obliga a pasar a Pro ($20 por usuario/mes, con $20 de crédito de uso mensual incluido por asiento).
Estos son los límites incluidos a día de hoy:
| Recurso | Hobby | Pro (incluido) |
|---|---|---|
| Transferencia de datos (egress) | 100 GB | 1 TB |
| Edge Requests | 1 M | 10 M |
| Invocaciones de funciones | 1 M | Bajo crédito de uso |
| Active CPU | 4 h | Bajo crédito de uso |
| Image Optimization (transformaciones) | 5 K/mes | 5 K/mes |
| Build (CPU minutes) | Incluido con límite | Incluido + on-demand |
| Uso comercial | No | Sí |
La diferencia clave no es solo la cuota: el Hobby tiene límites duros (si los superas, se corta), mientras que el Pro es elástico y factura el exceso. Eso es cómodo y peligroso a partes iguales.
Con el crédito de $20 por asiento, un proyecto pequeño (decenas de miles de visitas al mes) suele quedar cubierto: pagas los $20 del asiento y poco más. El punto de inflexión llega alrededor de 1 TB de egress mensual. A partir de ahí, cada recurso factura por separado y las cifras escalan rápido.
Las sorpresas más comunes en la factura:
fetch) no cuenta. Un await lento no te cuesta CPU, pero un render pesado sí.middleware.ts corre en todas las rutas (incluidos assets), multiplicas invocaciones sin darte cuenta.El error típico es mirar solo el bandwidth y olvidar que hay siete u ocho contadores corriendo en paralelo.
Lo que sí cumple Vercel es el rendimiento base:
<Suspense> para que el contenido crítico llegue antes mientras lo pesado sigue cargando.Un patrón de streaming con Suspense en el App Router:
import { Suspense } from "react";
export default function Page() {
return (
<section>
<Header /> {/* llega al instante */}
<Suspense fallback={<PostsSkeleton />}>
<Posts /> {/* async, no bloquea el resto */}
</Suspense>
</section>
);
}
async function Posts() {
const posts = await fetchPosts(); // se transmite cuando resuelve
return <PostList posts={posts} />;
}
Cada página regenerada por ISR es una página que no invoca una función serverless en cada visita. En un blog, servir contenido estático revalidado cada hora en lugar de renderizar en cada request cambia por completo el consumo de CPU y funciones:
// app/blog/[slug]/page.tsx
export const revalidate = 3600; // revalida como mucho cada hora
export async function generateStaticParams() {
const posts = await fetchAllSlugs();
return posts.map((slug) => ({ slug }));
}
El componente <Image> es potente, pero cada tamaño y formato distinto genera una transformación facturable. Limita los sizes, sirve dimensiones razonables y, si tienes muchísimas imágenes, valora un loader externo o desactivar la optimización para assets que ya vienen optimizados:
import Image from "next/image";
<Image
src="/portada.webp"
alt="Portada"
width={1200}
height={630}
sizes="(max-width: 768px) 100vw, 800px"
/>
Cada fetch sin cachear en un Server Component puede convertirse en una invocación con su Active CPU y su Fast Origin Transfer. Marca explícitamente qué se cachea y qué no:
// Cacheado y revalidado: barato
const data = await fetch(url, { next: { revalidate: 60 } });
// Siempre dinámico: úsalo solo cuando de verdad lo necesites
const live = await fetch(url, { cache: "no-store" });
No todo debe correr en el edge. El Edge Runtime es ideal para lógica ligera y con baja latencia (redirecciones, geolocalización, A/B testing en middleware). Para trabajo pesado, acceso a bases de datos o librerías Node completas, las funciones serverless (Node runtime) suelen salir más rentables y sencillas.
// Solo si la lógica es ligera y necesitas latencia mínima
export const runtime = "edge";
Y mantén el middleware.ts acotado con un matcher para que no corra en assets estáticos:
export const config = {
matcher: ["/((?!_next/static|_next/image|favicon.ico).*)"],
};
| Opción | Fuerte en | Flojo en | Cuándo elegirla |
|---|---|---|---|
| Vercel | DX, previews, ISR, integración Next.js | Egress caro a escala | Equipos que priorizan velocidad de entrega |
| Netlify | DX similar, buen tier gratuito | Mismo modelo de egress caro | Alternativa directa a Vercel |
| Cloudflare | Egress gratis, red enorme | Menos "plug & play" con Next.js | Mucho tráfico y sensibilidad al bandwidth |
| Self-hosting (VPS/Docker) | Coste fijo y predecible | Tú gestionas todo (CI, escalado, HTTPS) | Tráfico alto o factura descontrolada |
La conclusión práctica: por debajo de ~1 TB de egress al mes y con un equipo pequeño, Vercel es difícil de superar en relación productividad/coste. Por encima de ese umbral, o cuando el middleware y las imágenes disparan contadores en cada request, toca hacer números: Cloudflare (egress gratis) o un VPS con Next.js en Docker pueden dividir la factura entre varios.
Antes de que la factura te sorprenda:
Vercel no es caro por definición; es caro cuando lo usas como si el render dinámico fuese gratis. Con caché agresiva y contadores bajo control, el plan Pro cunde muchísimo antes de plantearte mudarte.
Cache Components cambia el modelo mental del cacheo en Next.js: en vez de heurísticas implícitas, marcas explícitamente con "use cache" qué partes de tu app pueden cachearse.
Next.js 16 llega con Turbopack estable, params/searchParams totalmente async y el cambio de middleware a proxy. Repaso los pasos y el codemod para migrar sin sustos.