Платформа Vercel представляет собой специализированную бессерверную инфраструктуру (Serverless PaaS), скомпонованную поверх глобальной сети Anycast CDN и вычислительных мощностей гиперскейлеров (преимущественно AWS). В отличие от классического хостинга на виртуальных машинах (EC2, Droplets), где единственный долгоживущий процесс Node.js обрабатывает входящие HTTP-соединения через системный сокет, Vercel декомпозирует сборку Next.js на три изолированных слоя исполнения:
fetch (Vercel Data Cache), синхронизируемое между всеми PoP планеты в фоновом режиме.Понимание этой трехуровневой декомпозиции критично для проектирования надежных Enterprise-систем, предотвращения каскадных сбоев при пиковых нагрузках и соблюдения жестких SLA по задержкам (TTFB) и бюджетам памяти.
Входящий запрос от клиента не направляется напрямую в монолитный сервер. Он проходит через эшелонированный маршрутизатор платформы, где каждый шаг отсекает сетевые задержки:
Входящий клиентский запрос (HTTPS / Anycast IP)
│
▼
┌─────────────────────────────────────────────────────────┐
│ Vercel Edge Network (PoP) │
│ - TLS 1.3 Termination, DDoS Mitigation │
│ - Проверка Edge Middleware (auth, routing, rewrites) │
│ - Обращение к Edge Cache (Static Assets, .next/static) │
└───────────┬─────────────────────────────────┬───────────┘
│ HIT (200 OK) │ MISS / Dynamic
▼ ▼
┌───────────────────────┐ ┌───────────────────────────────────────┐
│ Anycast Edge Cache │ │ Vercel Shared ISR / Data Cache │
│ (Assets / Images) │ │ (Глобальное персистентное S3/Blob) │
└───────────────────────┘ └───────────────────┬───────────────────┘
│ SWR Revalidation
▼
┌───────────────────────────────────────┐
│ Serverless Function (Node.js/AWS) │
│ - SSR рендеринг App Router (RSC) │
│ - Server Actions / Route Handlers │
│ - Доступ к базам данных (Postgres) │
└───────────────────────────────────────┘Определение физического расположения первичной базы данных и фиксация региона исполнения Serverless Functions в vercel.json (например, fra1 или hnd1) для предотвращения трансграничного сетевого оверхенда.
Аудит кодовой базы: вынос тяжелых операций ввода-вывода и рендеринга RSC в Node.js Serverless, а легковесной маршрутизации, геолокации и проверки JWT — в Edge Middleware.
Внедрение детерминированных ключей кэширования для fetch-запросов и организация вебхуков инвалидации по тегам (revalidateTag) из CMS и каталога продуктов.
Включение Vercel Deployment Protection (SAML/SSO), генерация криптографического секрета VERCEL_AUTOMATION_BYPASS_SECRET и добавление заголовков в E2E-тестовые раннеры.
Активация Vercel Speed Insights и OpenTelemetry трейсинга для контроля TTFB, LCP и времени холодного старта бессерверных функций в реальном времени.
В чем заключается принципиальная архитектурная разница между исполнением кода в Vercel Edge Middleware и Serverless Functions?
x-vercel-ip-country, определяет юрисдикцию пользователя и выполняет URL Rewrite на региональный суб-путь без дополнительного сетевого прыжка к центральной базе данных.tags: ['article-1024', 'category-breaking']. При публикации редакторской правки в headless CMS вебхук вызывает revalidateTag(), мгновенно инвалидируя кэш на всех континентальных PoP Vercel за 300 мс.x-vercel-protection-bypass.В Next.js 15+ разработчик имеет возможность явно объявлять рантайм для каждого сегмента маршрута (Route Segment Config). Эти рантаймы кардинально отличаются архитектурно:
В бессерверной среде файловая система /tmp каждого инстанса Lambda является строго эфемерной: при масштабировании нагрузки до 500 параллельных контейнеров каждый из них имеет собственный диск. Если бы Next.js сохранял закэшированные страницы на локальный диск, возникла бы критическая рассинхронизация данных (Cache Drift).
Платформа Vercel решает эту проблему через Shared Data Cache Architecture:
Запрос приходит на региональный Anycast PoP. Проверяется наличие скомпилированного HTML/RSC пэйлоуда в Global Edge Cache.
При промахе запрос маршрутизируется к ближайшей Serverless Function в выбранном регионе (например, fra1 / us-east-1). Функция выполняет рендеринг RSC.
Сгенерированный артефакт и метаданные кэша (включая связанные теги revalidateTag) асинхронно записываются в централизованное распределенное объектное хранилище Vercel.
Внешний вебхук вызывает revalidateTag('products'). Vercel Cache Bus рассылает сигнал инвалидации по всем глобальным PoP за доли секунды без пересборки приложения.
Критическим архитектурным ограничением Vercel является лимит входящего и исходящего тела запроса:
multipart/form-data на эндпоинт Route Handler или Server Action приведет к мгновенному возврату ошибки 413 Payload Too Large на уровне обратного прокси Vercel, даже не доходя до кода функции.import { NextResponse, type NextRequest } from 'next/server';
import { put } from '@vercel/blob';
export const runtime = 'nodejs';
// 1. Клиент запрашивает генерацию подписанной сессии загрузки
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 }
);
}
// Валидация MIME-типов для предотвращения загрузки исполняемых файлов
const allowedMimeTypes = ['image/jpeg', 'image/png', 'image/webp', 'application/pdf'];
if (!allowedMimeTypes.includes(contentType)) {
return NextResponse.json(
{ error: 'Unsupported media type' },
{ status: 415 }
);
}
// Генерация прямого загрузочного токена в Vercel Blob
// Загрузка файла 100+ МБ будет происходить напрямую из браузера в CDN-хранилище
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 });
}
}Ниже представлена эталонная конфигурация для продакшен-репозитория Next.js 15: манифест vercel.json с тонкой настройкой регионов исполнения, бюджетов памяти, таймаутов и заголовков безопасности, а также middleware.ts с поддержкой обхода Preview Protection в автоматизированных E2E-тестах.
{
"$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 — Защита и маршрутизация на Edge
import { NextResponse, type NextRequest } from 'next/server';
export const config = {
matcher: [
/*
* Применяем middleware ко всем путям, исключая:
* - _next/static (статические бандлы)
* - _next/image (сервис оптимизации изображений)
* - favicon.ico, robots.txt, sitemap.xml
*/
'/((?!_next/static|_next/image|favicon.ico|robots.txt|sitemap.xml).*)',
],
};
export function middleware(request: NextRequest): NextResponse {
const { pathname } = request.nextUrl;
const response = NextResponse.next();
// 1. Извлечение информации о физической локации клиента из Anycast Edge Headers
const country = request.headers.get('x-vercel-ip-country') ?? 'US';
const city = request.headers.get('x-vercel-ip-city') ?? 'Unknown';
const ip = request.headers.get('x-real-ip') ?? request.ip ?? '127.0.0.1';
response.headers.set('x-client-geo-country', country);
response.headers.set('x-client-geo-city', encodeURIComponent(city));
// 2. Механизм Bypass Deployment Protection для CI/CD и E2E тестов (Playwright)
// В Preview Environments Vercel может требовать SSO/Password.
// Секретный токен позволяет пайплайну беспрепятственно тестировать сборку.
const bypassSecret = process.env.VERCEL_AUTOMATION_BYPASS_SECRET;
const providedBypassHeader = request.headers.get('x-vercel-protection-bypass');
if (bypassSecret && providedBypassHeader === bypassSecret) {
// Устанавливаем служебный cookie Vercel для сохранения сессии тестирования
response.cookies.set('__vdpl', bypassSecret, {
path: '/',
httpOnly: true,
secure: true,
sameSite: 'none',
maxAge: 3600, // 1 час на прогон тестов
});
}
// 3. Динамическая генерация криптографического Nonce для Content Security Policy
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;
}Почему передача бинарных файлов размером свыше 4.5 МБ напрямую через Server Actions или Route Handlers в Next.js на Vercel завершается ошибкой HTTP 413 Payload Too Large и как устранить ее архитектурно?
Разработчики создают эндпоинт /api/upload с использованием request.formData() и пытаются передавать файлы размером 20–50 МБ (видеоматериалы, тяжелые PDF или архивы). В локальном окружении Node.js всё работает без сбоев.
В продакшене на Vercel обратный прокси Anycast обрывает соединение с кодом 413 FUNCTION_PAYLOAD_TOO_LARGE, так как жесткий лимит шлюза AWS Lambda / Vercel составляет 4.5 МБ.
// ❌ Фатальная ошибка в Serverless: запрос будет аварийно прерван прокси-сервером
export async function POST(request: Request) {
const formData = await request.formData();
const file = formData.get('largeFile') as File; // Ошибка 413 при размере > 4.5 МБ
await saveToDatabase(file);
return NextResponse.json({ ok: true });
}
// ✅ Правильное решение: Client-Side Direct Upload via Presigned URL
// Маршрутизатор Next.js только подписывает токен доступа (payload несколько байт),
// а браузер передает поток байтов напрямую в бакет S3 / Vercel Blob.Разработчик пытается выполнить проверку прав пользователя или блокировку сессии через прямое обращение к Prisma ORM или pg пулу внутри middleware.ts.
Edge Middleware выполняется в изолированном рантайме V8, где полностью отсутствуют системные сокеты операционной системы (модуль net). Сборка завершается критической ошибкой компилятора Turbopack/Webpack: Module not found: Can't resolve 'net'.
// ❌ Фатальная ошибка в middleware.ts: Edge Runtime не поддерживает TCP
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient(); // Крах рантайма
export async function middleware(req: NextRequest) {
const user = await prisma.user.findUnique({ where: { id: '...' } });
return NextResponse.next();
}
// ✅ Правильное решение: Валидация криптографической подписи JWT на границе без обращения к базе данных
// Либо обращение через HTTP-based драйвер (Neon Serverless Driver, Upstash Redis HTTP API).В Enterprise-подписке для безопасности включается SSO или Password Protection на все Preview Environments, чтобы исходный код и предрелизный контент не утекли в публичный интернет. После этого ночные запуски Playwright / GitHub Actions начинают массово падать с кодом 401 Unauthorized, получая HTML-страницу логина Vercel вместо тестируемого интерфейса.
// ❌ Ошибка: запуск тестов против заблокированного Preview URL без передачи bypass-заголовков
// playwright.config.ts
export default defineConfig({
use: {
baseURL: process.env.VERCEL_PREVIEW_URL, // Тесты получают HTTP 401 Authentication Required
},
});
// ✅ Правильное решение: Инъекция Vercel Protection Bypass заголовков в конфигурацию браузера
// 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',
},
},
});По умолчанию Vercel разворачивает Serverless Functions в регионе Вашингтон, США (iad1 — us-east-1). Если база данных приложения (Amazon RDS Postgres) расположена во Франкфурте (eu-central-1), то каждый SSR-запрос или Server Action совершает трансатлантический сетевой переход с задержкой 100–120 мс на каждый SQL-запрос.
Для исправления необходимо явно фиксировать параметр regions: ["fra1"] в корневом файле vercel.json, синхронизируя регион вычислений с регионом базы данных.