| name | vercel |
| description | Vercel deployment, serverless functions, and edge configuration. Use when user mentions "vercel", "vercel deploy", "vercel CLI", "serverless functions", "edge functions", "vercel.json", "preview deployments", "vercel domains", "vercel env", "vercel cron", "vercel KV", "vercel postgres", "vercel blob", "ISR", or deploying web applications to Vercel. |
Vercel
CLI Essentials
npm i -g vercel
vercel login
vercel link
vercel
vercel --prod
vercel dev
vercel dev --listen 4000
vercel env ls
vercel env add SECRET_KEY
vercel env add DATABASE_URL production < .env.production
vercel env pull .env.local
vercel env rm SECRET_KEY production
vercel domains ls
vercel domains add example.com
vercel domains inspect example.com
vercel logs https://my-deploy-url.vercel.app
vercel inspect <deployment-url>
vercel ls
vercel rollback <deployment-url>
Project Configuration (vercel.json)
{
"rewrites": [
{ "source": "/api/:path*", "destination": "/api/:path*" },
{ "source": "/(.*)", "destination": "/index.html" }
],
"redirects": [
{ "source": "/old-page", "destination": "/new-page", "permanent": true },
{ "source": "/blog/:slug", "destination": "https://blog.example.com/:slug", "statusCode": 308 }
],
"headers": [
{
"source": "/api/(.*)",
"headers": [
{ "key": "Access-Control-Allow-Origin", "value": "*" },
{ "key": "Cache-Control", "value": "s-maxage=86400" }
]
}
],
"functions": {
"api/heavy-task.ts": {
"memory": 1024,
"maxDuration": 60
},
"api/edge-fn.ts": {
"runtime": "edge"
}
},
"crons": [
{
"path": "/api/cron/daily-cleanup",
"schedule": "0 0 * * *"
},
{
"path": "/api/cron/hourly-sync",
"schedule": "0 * * * *"
}
],
"buildCommand": "npm run build",
"outputDirectory": "dist",
"installCommand": "npm ci",
"framework": "nextjs",
"regions": ["iad1", "sfo1"],
"cleanUrls": true,
"trailingSlash": false
}
Framework Detection and Build Settings
Vercel auto-detects frameworks: Next.js, Nuxt, SvelteKit, Remix, Astro, Vite, CRA, Gatsby, Angular, Hugo, etc. Override in project settings or vercel.json when auto-detection fails.
{
"framework": "vite",
"buildCommand": "vite build",
"outputDirectory": "dist",
"installCommand": "pnpm install",
"devCommand": "vite dev --port $PORT"
}
Node.js version: set in package.json engines field or project settings. Supports 18.x (default) and 20.x.
Environment Variables
Three scopes: Development, Preview, Production.
- Production: available only on production deployments
- Preview: available on preview deployments (each PR gets one)
- Development: available when running
vercel dev
System env vars are auto-injected: VERCEL_ENV, VERCEL_URL, VERCEL_BRANCH_URL, VERCEL_GIT_COMMIT_SHA, VERCEL_GIT_COMMIT_REF.
Sensitive values: mark as "Sensitive" in dashboard (encrypted, never shown in logs). For local dev, use vercel env pull to sync to .env.local.
Serverless Functions
Place files in the /api directory. Each file becomes an endpoint matching its path.
import type { VercelRequest, VercelResponse } from '@vercel/node';
export default function handler(req: VercelRequest, res: VercelResponse) {
const { name = 'World' } = req.query;
res.status(200).json({ message: `Hello ${name}!` });
}
Streaming Responses
import type { VercelRequest, VercelResponse } from '@vercel/node';
export default async function handler(req: VercelRequest, res: VercelResponse) {
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');
for (let i = 0; i < 5; i++) {
res.write(`data: chunk ${i}\n\n`);
await new Promise((r) => setTimeout(r, 500));
}
res.end();
}
Runtime Options
export const config = {
maxDuration: 30,
memory: 512,
};
Supported runtimes: Node.js (default), Go, Python, Ruby. Install @vercel/python, @vercel/go, etc. for non-Node runtimes.
Edge Functions
Run on Vercel's edge network (no cold starts, ~0ms startup, limited API surface).
export const config = { runtime: 'edge' };
export default function handler(request: Request) {
const country = request.headers.get('x-vercel-ip-country') || 'unknown';
const city = request.headers.get('x-vercel-ip-city') || 'unknown';
const latitude = request.headers.get('x-vercel-ip-latitude');
const longitude = request.headers.get('x-vercel-ip-longitude');
return Response.json({ country, city, latitude, longitude });
}
Middleware (Next.js)
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export function middleware(request: NextRequest) {
const country = request.geo?.country || 'US';
if (country !== 'US' && request.nextUrl.pathname === '/') {
return NextResponse.redirect(new URL(`/${country.toLowerCase()}`, request.url));
}
return NextResponse.next();
}
export const config = {
matcher: ['/((?!api|_next/static|favicon.ico).*)'],
};
Deployment Workflow
git push origin feature-branch
vercel
vercel --prod
vercel promote <deployment-url>
vercel rollback
Preview deployments get unique URLs: project-git-branch-team.vercel.app. Each PR comment shows the preview URL.
Custom Domains
vercel domains add myapp.com
vercel domains add www.myapp.com
vercel domains add "*.myapp.com"
DNS configuration:
- Apex domain (myapp.com): A record →
76.76.21.21
- Subdomain (www.myapp.com): CNAME →
cname.vercel-dns.com
- Nameservers (full control): point NS records to Vercel's nameservers
SSL certificates are auto-provisioned and renewed via Let's Encrypt.
Storage
Vercel KV (Redis-compatible)
import { kv } from '@vercel/kv';
await kv.set('user:123', { name: 'Alice', plan: 'pro' });
const user = await kv.get('user:123');
await kv.set('session:abc', data, { ex: 3600 });
await kv.hset('config', { theme: 'dark', lang: 'en' });
const theme = await kv.hget('config', 'theme');
await kv.lpush('queue', 'task1');
const task = await kv.rpop('queue');
Vercel Postgres
import { sql } from '@vercel/postgres';
const { rows } = await sql`SELECT * FROM users WHERE id = ${userId}`;
await sql`INSERT INTO users (name, email) VALUES (${name}, ${email})`;
import { db } from '@vercel/postgres';
const client = await db.connect();
try {
await client.sql`BEGIN`;
await client.sql`UPDATE accounts SET balance = balance - ${amount} WHERE id = ${fromId}`;
await client.sql`UPDATE accounts SET balance = balance + ${amount} WHERE id = ${toId}`;
await client.sql`COMMIT`;
} catch (e) {
await client.sql`ROLLBACK`;
throw e;
} finally {
client.release();
}
Vercel Blob
import { put, del, list, head } from '@vercel/blob';
const blob = await put('avatars/user-123.png', file, { access: 'public' });
console.log(blob.url);
const blob = await put(filename, body, {
access: 'public',
contentType: 'image/png',
addRandomSuffix: true,
});
const { blobs } = await list({ prefix: 'avatars/' });
const metadata = await head(blob.url);
await del(blob.url);
Edge Config (Feature Flags)
Ultra-low latency key-value store read at the edge (~0ms reads).
import { get, getAll, has } from '@vercel/edge-config';
const isEnabled = await get<boolean>('new-dashboard');
const allFlags = await getAll();
const exists = await has('maintenance-mode');
import { NextResponse } from 'next/server';
import { get } from '@vercel/edge-config';
export async function middleware() {
const maintenance = await get<boolean>('maintenance-mode');
if (maintenance) {
return NextResponse.rewrite(new URL('/maintenance', request.url));
}
return NextResponse.next();
}
Update Edge Config via API or dashboard. Changes propagate globally in ~seconds.
ISR (Incremental Static Regeneration)
Time-based ISR (Next.js App Router)
export const revalidate = 60;
export default async function Products() {
const products = await fetch('https://api.example.com/products').then(r => r.json());
return <ProductList products={products} />;
}
On-demand Revalidation
import { revalidatePath, revalidateTag } from 'next/cache';
import { NextRequest } from 'next/server';
export async function POST(request: NextRequest) {
const secret = request.headers.get('x-revalidation-secret');
if (secret !== process.env.REVALIDATION_SECRET) {
return Response.json({ error: 'Invalid secret' }, { status: 401 });
}
const { path, tag } = await request.json();
if (tag) revalidateTag(tag);
else if (path) revalidatePath(path);
return Response.json({ revalidated: true, now: Date.now() });
}
curl -X POST https://myapp.com/api/revalidate \
-H "x-revalidation-secret: $SECRET" \
-H "Content-Type: application/json" \
-d '{"path": "/products"}'
Monorepo Support
{
"projects": [
{ "name": "web", "rootDirectory": "apps/web" },
{ "name": "docs", "rootDirectory": "apps/docs" }
]
}
In project settings (dashboard or CLI):
- Root Directory:
apps/web — Vercel only builds this subdirectory
- Include/Ignore Build Step: skip builds when no relevant files changed
git diff --quiet HEAD^ HEAD -- apps/web/ packages/shared/ || exit 0
Works with Turborepo, Nx, pnpm workspaces. Vercel auto-detects Turborepo and uses turbo run build --filter=<project>.
Speed Insights and Web Analytics
npm i @vercel/speed-insights @vercel/analytics
import { SpeedInsights } from '@vercel/speed-insights/next';
import { Analytics } from '@vercel/analytics/react';
export default function RootLayout({ children }) {
return (
<html>
<body>
{children}
<SpeedInsights />
<Analytics />
</body>
</html>
);
}
Speed Insights tracks Core Web Vitals (LCP, FID, CLS, TTFB, INP) with real user data. Analytics provides pageviews, unique visitors, and referrers — no cookies, GDPR-compliant.
Deployment Protection
{
"passwordProtection": {
"deploymentType": "preview"
}
}
Options:
- Vercel Authentication: only team members can view (enabled by default for preview deployments)
- Password Protection (Pro+): set a shared password for preview or all deployments
- Trusted IPs (Enterprise): restrict access by IP range
- Deployment Protection Bypass: generate bypass URLs for CI/testing with
x-vercel-protection-bypass header
Troubleshooting
Build Failures
vercel logs <deployment-url>
vercel inspect <deployment-url>
Common causes:
- Missing env vars in build scope (add to "Preview" and "Production")
- Node.js version mismatch (set in package.json engines or project settings)
- Out of memory: increase function memory or optimize build (
NODE_OPTIONS=--max-old-space-size=4096)
- Missing dependencies: ensure
devDependencies aren't pruned if needed at build time
Function Timeouts
- Hobby: 60s max, Pro: 300s, Enterprise: 900s
- Use streaming for long-running responses
- Offload to background jobs (use Vercel Cron or external queue)
- Set
maxDuration in function config to extend timeout
Cold Starts
- Serverless functions: 250ms–1s cold start typical
- Reduce cold starts: keep bundles small, minimize imports, use dynamic imports
- Edge functions: no cold starts (~0ms startup)
- Use
@vercel/functions warm-up pattern for critical paths
Cost Optimization
- Function duration: minimize execution time; use edge functions where possible (cheaper, no cold start)
- Bandwidth: enable compression, optimize images with
next/image, set cache headers (s-maxage, stale-while-revalidate)
- Edge caching: use
Cache-Control: s-maxage=31536000 on static assets; ISR reduces function invocations
- Function invocations: batch operations, use SWR/React Query to reduce API calls
- Image optimization: set
images.minimumCacheTTL in next.config.js to reduce re-optimizations
- Serverless regions: deploy functions to a single region near your database to reduce latency and cost
- Bundle size: tree-shake, lazy-load routes, use
@vercel/nft to trace dependencies accurately