La plataforma Vercel constituye una infraestructura sin servidor de nivel empresarial (Serverless PaaS), diseñada sobre una red global Anycast CDN combinada con la capacidad de computación de hiperescaladores (predominantemente AWS). A diferencia del alojamiento tradicional en máquinas virtuales con estado (EC2, Droplets), donde un único proceso Node.js de larga duración atiende conexiones HTTP a través de un socket del sistema operativo, Vercel descompone el compilado de Next.js en tres capas de ejecución desacopladas:
fetch (Vercel Data Cache), sincronizado en segundo plano entre todos los PoP del planeta.Comprender esta descomposición de tres capas es crucial para diseñar sistemas corporativos resilientes, evitar caídas en cascada durante picos masivos de tráfico y cumplir estrictos acuerdos de nivel de servicio (SLA) de latencia (TTFB) y presupuestos de memoria.
Una petición cliente entrante nunca se envía de forma directa a un servidor monolítico central. En su lugar, atraviesa un router escalonado donde cada fase elimina saltos innecesarios de latencia:
Petición cliente entrante (HTTPS / Anycast IP)
│
▼
┌─────────────────────────────────────────────────────────┐
│ Vercel Edge Network (PoP) │
│ - Terminación TLS 1.3, Mitigación DDoS │
│ - Ejecución de Edge Middleware (auth, routing, rewrite)│
│ - Búsqueda en Edge Cache (archivos estáticos) │
└───────────┬─────────────────────────────────┬───────────┘
│ HIT (200 OK) │ MISS / Dynamic
▼ ▼
┌───────────────────────┐ ┌───────────────────────────────────────┐
│ Anycast Edge Cache │ │ Vercel Shared ISR / Data Cache │
│ (Assets / Images) │ │ (Almacenamiento persistente global)│
└───────────────────────┘ └───────────────────┬───────────────────┘
│ SWR Revalidation
▼
┌───────────────────────────────────────┐
│ Serverless Function (Node.js/AWS) │
│ - Renderizado SSR y RSC App Router │
│ - Server Actions / Route Handlers │
│ - Conexión a bases de datos (TCP) │
└───────────────────────────────────────┘x-vercel-ip-country, determina el país del cliente y ejecuta un URL Rewrite hacia una subruta regional sin realizar una llamada de red transcontinental a la base de datos principal.tags: ['article-1024', 'breaking-news']. Cuando un redactor publica una corrección en el CMS headless, un webhook entrante ejecuta revalidateTag(), purgando la caché en todos los PoP globales de Vercel en menos de 300 ms.x-vercel-protection-bypass.En Next.js 15+, los desarrolladores pueden declarar explícitamente el entorno de ejecución para cada segmento de ruta mediante Route Segment Config. Estos entornos presentan diferencias arquitectónicas fundamentales:
En una arquitectura serverless, el sistema de archivos /tmp de cada micro-VM Lambda es estrictamente efímero: ante una escala de cientos de peticiones simultáneas, cada contenedor dispone de un disco local aislado. Si Next.js guardase las páginas en caché en el disco local, se produciría una desincronización grave (Cache Drift).
Vercel resuelve este reto mediante su arquitectura Shared Data Cache:
La petición alcanza el punto Anycast PoP más próximo. Edge Cache comprueba si existe un artefacto HTML/RSC precompilado.
Ante un fallo de caché, la petición se enruta a la Serverless Function más cercana en la región asignada (ej. fra1 / us-east-1) para ejecutar el renderizado RSC.
El nuevo contenido RSC generado y los metadatos de caché (incluyendo vinculaciones de revalidateTag) se persisten en el almacenamiento distribuido central de Vercel.
Un webhook externo ejecuta revalidateTag('products'). El Vercel Cache Bus propaga la señal de purga a todos los PoP globales en milisegundos sin redespliegue.
Una restricción operativa crítica en Vercel es el límite de tamaño de las peticiones entrantes:
multipart/form-data convencional hacia un Route Handler o Server Action provocará un error inmediato 413 FUNCTION_PAYLOAD_TOO_LARGE en el proxy inverso perimetral antes de que se ejecute el código de la función.import { NextResponse, type NextRequest } from 'next/server';
import { put } from '@vercel/blob';
export const runtime = 'nodejs';
// 1. El cliente solicita la emisión de un ticket de carga autorizado
export async function POST(request: NextRequest): Promise<NextResponse> {
try {
const { filename, contentType } = (await request.json()) as {
filename: string;
contentType: string;
};
if (!filename || !contentType) {
return NextResponse.json(
{ error: 'Filename and contentType are required' },
{ status: 400 }
);
}
// Validación de tipos MIME para prevenir la subida de scripts ejecutables
const allowedMimeTypes = ['image/jpeg', 'image/png', 'image/webp', 'application/pdf'];
if (!allowedMimeTypes.includes(contentType)) {
return NextResponse.json(
{ error: 'Unsupported media type' },
{ status: 415 }
);
}
// Generar un descriptor de carga directa en Vercel Blob
// Archivos de más de 100 MB se transfieren directamente desde el navegador a la nube
const blob = await put(`uploads/${crypto.randomUUID()}-${filename}`, '', {
access: 'public',
addRandomSuffix: true,
});
return NextResponse.json({ uploadUrl: blob.url });
} catch (error) {
const message = error instanceof Error ? error.message : 'Internal Server Error';
return NextResponse.json({ error: message }, { status: 500 });
}
}La siguiente configuración representa el estándar de producción para Next.js 15: un manifiesto vercel.json con fijación regional de computación, cuotas de memoria y cabeceras de seguridad, junto a un middleware.ts con capacidad de evasión de Deployment Protection para pruebas automáticas.
{
"$schema": "https://openapi.vercel.sh/vercel.json",
"framework": "nextjs",
"cleanUrls": true,
"trailingSlash": false,
"regions": ["fra1"],
"functions": {
"app/api/**/*": {
"memory": 1024,
"maxDuration": 60
},
"app/**/*": {
"memory": 1536,
"maxDuration": 30
}
},
"headers": [
{
"source": "/(.*)",
"headers": [
{
"key": "X-Content-Type-Options",
"value": "nosniff"
},
{
"key": "X-Frame-Options",
"value": "DENY"
},
{
"key": "Referrer-Policy",
"value": "strict-origin-when-cross-origin"
},
{
"key": "Permissions-Policy",
"value": "camera=(), microphone=(), geolocation=(), browsing-topics=()"
},
{
"key": "Strict-Transport-Security",
"value": "max-age=63072000; includeSubDomains; preload"
}
]
},
{
"source": "/_next/static/(.*)",
"headers": [
{
"key": "Cache-Control",
"value": "public, max-age=31536000, immutable"
}
]
}
]
}// middleware.ts — Seguridad perimetral y enrutamiento en Edge
import { NextResponse, type NextRequest } from 'next/server';
export const config = {
matcher: [
/*
* Interceptar todas las rutas excepto:
* - _next/static (archivos estáticos empaquetados)
* - _next/image (servicio de optimización de imágenes)
* - favicon.ico, robots.txt, sitemap.xml
*/
'/((?!_next/static|_next/image|favicon.ico|robots.txt|sitemap.xml).*)',
],
};
export function middleware(request: NextRequest): NextResponse {
const response = NextResponse.next();
// 1. Extraer metadatos de ubicación geográfica del cliente desde cabeceras Anycast
const country = request.headers.get('x-vercel-ip-country') ?? 'US';
const city = request.headers.get('x-vercel-ip-city') ?? 'Unknown';
response.headers.set('x-client-geo-country', country);
response.headers.set('x-client-geo-city', encodeURIComponent(city));
// 2. Mecanismo de omisión de Deployment Protection para CI/CD y pruebas E2E (Playwright)
// En Preview Environments, Vercel exige SSO o clave de acceso.
// Un secreto criptográfico permite al ejecutor de pruebas automatizadas saltarse esta pantalla.
const bypassSecret = process.env.VERCEL_AUTOMATION_BYPASS_SECRET;
const providedBypassHeader = request.headers.get('x-vercel-protection-bypass');
if (bypassSecret && providedBypassHeader === bypassSecret) {
// Establecer la cookie de sesión interna de Vercel para autorizar la prueba
response.cookies.set('__vdpl', bypassSecret, {
path: '/',
httpOnly: true,
secure: true,
sameSite: 'none',
maxAge: 3600, // 1 hora de margen para la suite de pruebas
});
}
// 3. Generación dinámica de Nonce criptográfico para Content Security Policy (CSP)
const nonce = Buffer.from(crypto.randomUUID()).toString('base64');
const cspHeader = `
default-src 'self';
script-src 'self' 'nonce-${nonce}' 'strict-dynamic';
style-src 'self' 'nonce-${nonce}';
img-src 'self' blob: data: https:;
font-src 'self';
connect-src 'self' https://vitals.vercel-insights.com;
frame-ancestors 'none';
base-uri 'self';
form-action 'self';
`.replace(/\s{2,}/g, ' ').trim();
response.headers.set('x-nonce', nonce);
response.headers.set('Content-Security-Policy', cspHeader);
return response;
}Los ingenieros implementan un endpoint /api/upload con request.formData() e intentan subir vídeos o archivos PDF de 20 a 50 MB. Aunque funciona sin problemas en el entorno local de Node.js, falla de inmediato en producción en Vercel.
El proxy inverso Anycast corta la conexión arrojando 413 FUNCTION_PAYLOAD_TOO_LARGE debido a que la infraestructura de entrada de AWS Lambda impone un límite infranqueable de 4.5 MB por petición.
// ❌ ERROR CRÍTICO EN SERVERLESS: Cancelado por el proxy antes de ejecutar la función
export async function POST(request: Request) {
const formData = await request.formData();
const file = formData.get('largeFile') as File; // Falla con 413 si el archivo supera 4.5 MB
await saveToDatabase(file);
return NextResponse.json({ ok: true });
}
// ✅ SOLUCIÓN ARQUITECTÓNICA: Subida directa del cliente mediante Presigned URL
// El servidor Next.js solo firma un token de autorización (payload de pocos bytes),
// y el navegador transfiere los bytes directamente al bucket S3 o Vercel Blob.Intentar consultar PostgreSQL mediante Prisma ORM o el driver pg directamente dentro de middleware.ts.
Edge Middleware se ejecuta en aislamientos V8 que carecen del módulo net de Node.js indispensable para abrir sockets TCP directos. La compilación fallará con: Module not found: Can't resolve 'net'.
// ❌ ERROR CATASTRÓFICO en middleware.ts: Edge Runtime carece de sockets TCP directos
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient(); // Colapso en tiempo de ejecución
export async function middleware(req: NextRequest) {
const user = await prisma.user.findUnique({ where: { id: '...' } });
return NextResponse.next();
}
// ✅ SOLUCIÓN ARQUITECTÓNICA: Verificación criptográfica de firmas JWT en el perímetro sin llamadas a BD,
// o el uso de controladores sobre HTTP/WebSockets (Neon Serverless Driver, Upstash Redis).Al activar la protección de despliegue (SSO o contraseña) en los Preview Environments, las pruebas nocturnas de Playwright en GitHub Actions fallan en masa con 401 Unauthorized, recibiendo el formulario de inicio de sesión de Vercel en lugar de la aplicación web.
// ❌ CONFIGURACIÓN INCORRECTA: Playwright ataca una URL protegida sin cabeceras de omisión
// playwright.config.ts
export default defineConfig({
use: {
baseURL: process.env.VERCEL_PREVIEW_URL, // Devuelve HTTP 401 Unauthorized
},
});
// ✅ CONFIGURACIÓN CORRECTA: Inyectar cabeceras de omisión de Vercel en el contexto del navegador
// playwright.config.ts
export default defineConfig({
use: {
baseURL: process.env.VERCEL_PREVIEW_URL,
extraHTTPHeaders: {
'x-vercel-protection-bypass': process.env.VERCEL_AUTOMATION_BYPASS_SECRET || '',
'x-vercel-set-bypass-cookie': 'true',
},
},
});Por defecto, Vercel aprovisiona las funciones serverless en el norte de Virginia, EE.UU. (iad1 / us-east-1). Si la base de datos PostgreSQL (por ejemplo, en AWS RDS) se ubica en Frankfurt (eu-central-1), cada renderizado del lado del servidor o Server Action sufrirá una penalización transatlántica de 100 a 120 ms por cada consulta SQL.
Se corrige declarando explícitamente regions: ["fra1"] en vercel.json para coubicar el cómputo con la base de datos.
Identificar la localización física de la base de datos y fijar la región de ejecución de Serverless Functions en vercel.json (ej. fra1, hnd1) para suprimir la latencia geográfica.
Segregar operaciones pesadas de acceso a datos y renderizado RSC en Serverless de Node.js, manteniendo el enrutamiento ligero, geolocalización y validación de tokens en Edge Middleware.
Implementar etiquetas deterministas en llamadas fetch y registrar webhooks entrantes para llamar a revalidateTag() bajo demanda sin reconstruir la aplicación.
Habilitar Vercel Deployment Protection (SAML/SSO), configurar VERCEL_AUTOMATION_BYPASS_SECRET y transmitir cabeceras de omisión en las suites de pruebas de Playwright.
Activar Vercel Speed Insights y telemetría con OpenTelemetry para auditar arranques en frío, TTFB y duraciones de ejecución de funciones sobre tráfico real.