Skip to main content
Technology & EngineeringDeployment Patterns303 lines

vercel-deployment

Comprehensive guide to deploying modern web applications on Vercel, covering framework-specific configuration for Next.js, SvelteKit, Astro, and Remix, along with environment variables, preview deployments, edge and serverless functions, ISR, custom domains, and monorepo support.

Quick Summary33 lines
Vercel auto-detects frameworks, but explicit configuration via `vercel.json` prevents surprises:

## Key Points

- **Production**: Only applied on `main` branch deployments.
- **Preview**: Applied on all non-production branches.
- **Development**: Only available via `vercel dev`.
1. **Not using `--frozen-lockfile`**: Leads to non-deterministic builds. Always freeze.
2. **Over-using serverless functions**: For simple data fetching, use ISR or server components instead.
3. **Ignoring cold starts**: Serverless functions cold-start takes 250-500ms. Use edge functions for latency-sensitive paths.
4. **Deploying without preview testing**: Always verify preview deployments before merging to production.
5. **Not setting `VERCEL_FORCE_NO_BUILD_CACHE=1`** when debugging build issues.
- [ ] `vercel.json` configured with correct framework and build commands
- [ ] Environment variables set for all scopes (production, preview, development)
- [ ] Custom domain configured with correct DNS records
- [ ] Preview deployments tested before merging

## Quick Example

```js
// remix.config.js — Remix v1 style
module.exports = {
  serverBuildTarget: 'vercel',
  server: process.env.NODE_ENV === 'development' ? undefined : './server.js',
};
```

```js
const isProduction = process.env.VERCEL_ENV === 'production';
const isPreview = process.env.VERCEL_ENV === 'preview';
```
skilldb get deployment-patterns-skills/vercel-deploymentFull skill: 303 lines
Paste into your CLAUDE.md or agent config

Deploying to Vercel

Framework Detection and Project Configuration

Vercel auto-detects frameworks, but explicit configuration via vercel.json prevents surprises:

{
  "framework": "nextjs",
  "buildCommand": "pnpm build",
  "outputDirectory": ".next",
  "installCommand": "pnpm install --frozen-lockfile",
  "regions": ["iad1"]
}

Next.js

Next.js is Vercel's first-class citizen. Key configuration in next.config.js:

/** @type {import('next').NextConfig} */
const nextConfig = {
  output: 'standalone',        // Smaller deployment bundles
  images: {
    remotePatterns: [
      { protocol: 'https', hostname: 'cdn.example.com' }
    ],
  },
  experimental: {
    ppr: true,                 // Partial Prerendering
  },
};
module.exports = nextConfig;

SvelteKit

Use the Vercel adapter:

// svelte.config.js
import adapter from '@sveltejs/adapter-vercel';

export default {
  kit: {
    adapter: adapter({
      runtime: 'edge',          // or 'nodejs18.x'
      regions: ['iad1'],
      split: true,              // Each route = separate function
    }),
  },
};

Astro

// astro.config.mjs
import { defineConfig } from 'astro/config';
import vercel from '@astrojs/vercel/serverless';

export default defineConfig({
  output: 'hybrid',            // Static by default, opt-in to SSR per route
  adapter: vercel({
    webAnalytics: { enabled: true },
    imageService: true,
  }),
});

Remix

// remix.config.js — Remix v1 style
module.exports = {
  serverBuildTarget: 'vercel',
  server: process.env.NODE_ENV === 'development' ? undefined : './server.js',
};

For Remix v2+, Vercel handles the Vite plugin automatically.

Environment Variables

Setting Variables

# Via CLI
vercel env add DATABASE_URL production
vercel env add DATABASE_URL preview
vercel env add DATABASE_URL development

# Pull to local .env
vercel env pull .env.local

Scoping Rules

  • Production: Only applied on main branch deployments.
  • Preview: Applied on all non-production branches.
  • Development: Only available via vercel dev.

Sensitive Variables

Mark variables as "Sensitive" in the dashboard to prevent them from appearing in build logs. Use VERCEL_ENV to detect the current environment at runtime:

const isProduction = process.env.VERCEL_ENV === 'production';
const isPreview = process.env.VERCEL_ENV === 'preview';

Anti-pattern: Committing .env files or hardcoding secrets in vercel.json. The env field in vercel.json is for referencing variable names, never values.

Preview Deployments

Every push to a non-production branch creates a unique preview URL:

https://my-project-git-feat-auth-username.vercel.app

Protecting Previews

// vercel.json
{
  "autoAssignCustomDomains": true,
  "passwordProtection": {
    "deploymentType": "preview"
  }
}

Or use Vercel Authentication to restrict to team members. For PR comments with deploy links, ensure the GitHub integration is installed.

Preview Environment per Branch

Use branch-specific env vars in the dashboard under Settings > Environment Variables. Filter by Git branch name to override specific values for feature branches.

Serverless Functions

Place API routes or serverless functions in api/ (standalone) or use your framework's native routing.

// api/hello.ts (standalone)
import type { VercelRequest, VercelResponse } from '@vercel/node';

export default function handler(req: VercelRequest, res: VercelResponse) {
  res.status(200).json({ message: 'Hello from serverless' });
}

Configuration

// vercel.json
{
  "functions": {
    "api/heavy-task.ts": {
      "memory": 1024,
      "maxDuration": 30
    }
  }
}

Anti-pattern: Using serverless functions for WebSocket connections. Serverless functions have a max duration (10s on Hobby, 60s on Pro). Use a persistent server on Fly.io or Railway for long-lived connections.

Edge Functions

Edge functions run on Vercel's edge network (V8 isolates, no Node.js APIs):

// app/api/geo/route.ts (Next.js App Router)
import { NextRequest } from 'next/server';

export const runtime = 'edge';

export function GET(request: NextRequest) {
  const country = request.geo?.country || 'Unknown';
  return Response.json({ country });
}

Edge middleware for auth checks:

// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

export function middleware(request: NextRequest) {
  const token = request.cookies.get('session');
  if (!token && request.nextUrl.pathname.startsWith('/dashboard')) {
    return NextResponse.redirect(new URL('/login', request.url));
  }
  return NextResponse.next();
}

export const config = {
  matcher: ['/dashboard/:path*'],
};

Anti-pattern: Importing heavy Node.js libraries in edge functions. They run on V8, not Node. Use lightweight alternatives or move to serverless runtime.

Incremental Static Regeneration (ISR)

ISR lets you update static pages without full rebuilds:

// app/products/[id]/page.tsx (Next.js App Router)
export const revalidate = 60; // Revalidate every 60 seconds

export default async function ProductPage({ params }) {
  const product = await fetch(`https://api.example.com/products/${params.id}`);
  return <div>{/* render product */}</div>;
}

On-Demand Revalidation

// app/api/revalidate/route.ts
import { revalidatePath, revalidateTag } from 'next/cache';
import { NextRequest } from 'next/server';

export async function POST(request: NextRequest) {
  const secret = request.headers.get('x-revalidate-secret');
  if (secret !== process.env.REVALIDATE_SECRET) {
    return Response.json({ error: 'Invalid secret' }, { status: 401 });
  }

  revalidateTag('products');
  return Response.json({ revalidated: true });
}

Custom Domains

vercel domains add example.com
vercel domains add www.example.com

DNS configuration: add an A record pointing to 76.76.21.21 and a CNAME for www pointing to cname.vercel-dns.com. Vercel auto-provisions TLS certificates.

Anti-pattern: Adding a domain before DNS propagation completes, then panicking about SSL errors. Give it 10-30 minutes.

Monorepo Support

Turborepo (Recommended)

// vercel.json at project root
{
  "buildCommand": "cd ../.. && npx turbo run build --filter=web",
  "installCommand": "pnpm install --frozen-lockfile",
  "framework": "nextjs"
}

Set the Root Directory in Vercel project settings to apps/web.

Ignored Build Step

Prevent unnecessary rebuilds:

#!/bin/bash
# .vercel/ignore-build-step.sh
echo "Checking for changes in apps/web..."
git diff HEAD^ HEAD --quiet -- apps/web/ packages/shared/

Or use the built-in path filter in project settings under Git > Ignored Build Step.

Common Anti-Patterns

  1. Not using --frozen-lockfile: Leads to non-deterministic builds. Always freeze.
  2. Over-using serverless functions: For simple data fetching, use ISR or server components instead.
  3. Ignoring cold starts: Serverless functions cold-start takes 250-500ms. Use edge functions for latency-sensitive paths.
  4. Deploying without preview testing: Always verify preview deployments before merging to production.
  5. Not setting VERCEL_FORCE_NO_BUILD_CACHE=1 when debugging build issues.

Deployment Checklist

  • vercel.json configured with correct framework and build commands
  • Environment variables set for all scopes (production, preview, development)
  • Custom domain configured with correct DNS records
  • Preview deployments tested before merging
  • Serverless function timeouts and memory configured
  • Build caching verified (check Turborepo remote cache if monorepo)
  • Error pages (404, 500) customized
  • Analytics and Speed Insights enabled

Install this skill directly: skilldb add deployment-patterns-skills

Get CLI access →

Related Skills

database-deployment

Comprehensive guide to database deployment for web applications, covering managed database services (PlanetScale, Neon, Supabase, Turso), migration strategies, connection pooling, backup and restore procedures, data seeding, and schema management best practices for production environments.

Deployment Patterns539L

docker-deployment

Comprehensive guide to using Docker for production deployments, covering multi-stage builds, .dockerignore optimization, layer caching strategies, health checks, Docker Compose for local development, container registries, and security scanning best practices.

Deployment Patterns479L

fly-io-deployment

Complete guide to deploying applications on Fly.io, covering flyctl CLI usage, Dockerfile-based deployments, fly.toml configuration, persistent volumes, horizontal and vertical scaling, multi-region deployments, managed Postgres and Redis, private networking, and auto-scaling strategies.

Deployment Patterns412L

github-actions-cd

Comprehensive guide to implementing continuous deployment with GitHub Actions, covering deploy workflows, environment protection rules, secrets management, matrix builds, dependency caching, artifact management, and deploying to multiple targets including Vercel, Fly.io, AWS, and container registries.

Deployment Patterns469L

monitoring-post-deploy

Comprehensive guide to post-deployment monitoring for web applications, covering uptime checks, error tracking with Sentry, application performance monitoring, log aggregation, alerting strategies, public status pages, and incident response procedures for production systems.

Deployment Patterns572L

netlify-deployment

Complete guide to deploying web applications on Netlify, covering build settings, deploy previews, serverless and edge functions, forms, identity, redirects and rewrites, split testing, and environment variable management for production workflows.

Deployment Patterns399L