The fastest and most reliable way to deploy your Next.js SaaS application to production.
Optimal for Next.js Apps:
SaaS-Specific Benefits:
Choose the deployment method that fits your workflow:
Automatic deployments from your repository:
Connect Repository
# Push your code to GitHub, GitLab, or Bitbucket
git push origin mainImport Project to Vercel
Configure Build Settings
Framework Preset: Next.js
Build Command: pnpm build
Output Directory: .next (automatic)
Install Command: pnpm install
Set Environment Variables
Benefits:
Manual deployments via command line:
Install Vercel CLI
npm i -g vercel
# or
pnpm add -g vercelLogin to Vercel
vercel loginDeploy to Production
# First deployment
vercel --prod
# Subsequent deployments
vercel --prodConfigure Project Settings
# Set up project configuration
vercel env add DATABASE_URL production
vercel env add AUTH_SECRET production
# ... add all environment variablesBenefits:
Critical Variables for Production:
# Core Application
DATABASE_URL="postgres://..."
AUTH_SECRET="your-auth-secret"
BETTER_AUTH_SECRET="same-as-auth-secret"
BETTER_AUTH_URL="https://yourdomain.com"
NEXT_PUBLIC_APP_URL="https://yourdomain.com"
# Email Service
RESEND_API_KEY="re_your_api_key"
EMAIL_FROM="noreply@yourdomain.com"
# File Storage
SUPABASE_URL="https://your-project.supabase.co"
SUPABASE_ANON_KEY="your-anon-key"
SUPABASE_BUCKET="your-bucket-name"
# Stripe Payment
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY="pk_live_..."
STRIPE_SECRET_KEY="sk_live_..."
STRIPE_WEBHOOK_SECRET="whsec_..."Navigate to Project Settings
Add Variables by Environment
Variable Name: DATABASE_URL
Value: postgres://user:pass@host:5432/db
Environments: ✓ Production ✓ Preview ✓ Development
Sensitive Variables
NEXT_PUBLIC_ only for public variables# Add single variable
vercel env add DATABASE_URL production
# Add from file
vercel env pull .env.vercel.local
# List all variables
vercel env lsSet up your custom domain for professional branding:
Domain Providers:
Project Settings → Domains
Domain: yourdomain.com
Redirect: www.yourdomain.com → yourdomain.com (recommended)
DNS Configuration
Type: A Record
Name: @
Value: 76.76.19.61 (Vercel's IP)
Type: CNAME
Name: www
Value: cname.vercel-dns.com
Vercel automatically provisions SSL certificates:
Verify SSL:
# Check certificate
curl -I https://yourdomain.com
# Response should include:
# HTTP/2 200
# strict-transport-security: max-age=63072000Optimize your build for production performance:
// next.config.ts
import type { NextConfig } from 'next'
const nextConfig: NextConfig = {
// Image optimization for global CDN
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'your-project.supabase.co', // Your Supabase domain
},
],
},
// Cache Components: 'use cache' directive, cacheLife/cacheTag, and Partial
// Prerendering by default. Replaces the removed experimental.useCache flag.
cacheComponents: true,
// Performance optimizations
experimental: {
authInterrupts: true,
taint: true,
staleTimes: {
dynamic: 30, // 30 seconds for dynamic content
static: 180, // 3 minutes for static content
},
},
}
export default nextConfig// vercel.json
{
"buildCommand": "pnpm build",
"devCommand": "pnpm dev",
"installCommand": "pnpm install",
"framework": "nextjs",
"functions": {
"src/app/api/**/*.ts": {
"maxDuration": 30
}
},
"headers": [
{
"source": "/api/(.*)",
"headers": [
{
"key": "Access-Control-Allow-Origin",
"value": "https://yourdomain.com"
}
]
}
]
}Package.json Scripts:
{
"scripts": {
"build": "next build --turbopack",
"start": "next start",
"verify-build": "next build && next export"
}
}Environment-Specific Builds:
# Production build with optimizations
NODE_ENV=production pnpm build
# Analyze bundle size
ANALYZE=true pnpm buildTrack your deployment performance:
Enable Built-in Analytics:
Key Metrics:
// lib/analytics.ts
import { Analytics } from '@vercel/analytics/react'
import { SpeedInsights } from '@vercel/speed-insights/next'
export function AnalyticsProviders({ children }: { children: React.ReactNode }) {
return (
<>
{children}
<Analytics />
<SpeedInsights />
</>
)
}Track API Performance:
// app/api/health/route.ts
export async function GET() {
const start = Date.now()
try {
// Check database connection
await db.select().from(users).limit(1)
const duration = Date.now() - start
return Response.json({
status: 'healthy',
timestamp: new Date().toISOString(),
database: 'connected',
responseTime: `${duration}ms`
})
} catch (error) {
return Response.json({
status: 'unhealthy',
error: 'Database connection failed'
}, { status: 500 })
}
}Ensure reliable and secure deployments:
# 1. Run all tests
pnpm test
pnpm test:e2e
# 2. Check build locally
pnpm build
# 3. Verify environment variables
pnpm env:check
# 4. Database migrations
pnpm db:generate
pnpm db:migrate
# 5. Security scan
pnpm audit1. Preview Deployments
# Deploy feature branch for testing
git checkout feature/new-payment-flow
git push origin feature/new-payment-flow
# Vercel automatically creates preview URL
# https://yourapp-git-feature-new-payment-flow-team.vercel.app2. Production Deployment
# After testing in preview
git checkout main
git merge feature/new-payment-flow
git push origin main
# Automatic production deploymentInstant Rollback via Dashboard:
Rollback via CLI:
# List recent deployments
vercel ls
# Rollback to specific deployment
vercel rollback [deployment-url]Environment Security:
Access Control:
// middleware.ts
export function middleware(request: NextRequest) {
// Block access to admin routes in preview deployments
if (request.nextUrl.hostname.includes('vercel.app') &&
request.nextUrl.pathname.startsWith('/admin')) {
return new Response('Access denied', { status: 403 })
}
}Solutions to frequent Vercel deployment problems:
Problem: Build timeout
# Solution: Optimize dependencies and build process
npm prune
pnpm store prune
# Use build cache
vercel build --prodProblem: Memory issues during build
// vercel.json
{
"functions": {
"app/api/**/*.ts": {
"memory": 1024
}
}
}Problem: Variables not accessible
// Debug environment variables
console.log('Environment check:', {
NODE_ENV: process.env.NODE_ENV,
DATABASE_URL: process.env.DATABASE_URL ? 'Set' : 'Missing',
STRIPE_SECRET: process.env.STRIPE_SECRET_KEY ? 'Set' : 'Missing'
})Problem: SSL certificate not provisioning
Problem: Custom domain not working
# Check DNS propagation
dig yourdomain.com
nslookup yourdomain.comProblem: API routes timing out
// Increase timeout in vercel.json
{
"functions": {
"app/api/**/*.ts": {
"maxDuration": 60
}
}
}Problem: CORS errors
// app/api/auth/[...better-auth]/route.ts
export async function OPTIONS(request: Request) {
return new Response(null, {
status: 200,
headers: {
'Access-Control-Allow-Origin': process.env.NEXT_PUBLIC_APP_URL || '*',
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
},
})
}Your SaaS application is now deployed on Vercel with enterprise-grade performance and reliability. Next, configure your Environment Variables for optimal security and functionality.