Saturday, April 12th 2025 · 5 min read

Deploying Your Next.js SaaS to Production: Complete Guide

A comprehensive guide to deploying Next.js SaaS applications to production. Covers Vercel, Railway, AWS, database setup, environment variables, monitoring, and production checklist.

You've built your SaaS application. Now it's time to deploy it to production where real users can access it. This guide covers everything from choosing a hosting provider to monitoring your live application.

Choosing a Hosting Provider

Vercel: The Default Choice

Vercel created Next.js and offers the most optimized deployment experience:

Pros:

  • Zero-config deployment
  • Edge network with 40+ regions
  • Automatic preview deployments
  • Built-in analytics and monitoring
  • Best-in-class caching

Cons:

  • Can get expensive at scale
  • Some advanced features require Pro plan
  • Vendor lock-in for some features

Best for: Most SaaS applications, especially those starting out.

Railway: Simple and Affordable

Railway offers a straightforward deployment experience with predictable pricing:

Pros:

  • Simple pricing ($5/month + usage)
  • Great developer experience
  • Built-in PostgreSQL and Redis
  • No cold starts

Cons:

  • Smaller edge network than Vercel
  • Fewer built-in analytics tools
  • Less documentation

Best for: Cost-conscious teams, applications with high compute needs.

AWS (Amplify or ECS)

AWS offers the most control and scalability:

Pros:

  • Maximum control and customization
  • Enterprise-grade security
  • Global infrastructure
  • Cost-effective at scale

Cons:

  • Steep learning curve
  • Complex configuration
  • More operational overhead

Best for: Enterprise applications, teams with DevOps expertise.

Comparison Table

FeatureVercelRailwayAWS Amplify
Setup Time5 min10 min30+ min
Minimum Cost$0$5/mo$0
Auto ScalingYesYesYes
Edge FunctionsYesNoYes
DatabaseSeparateBuilt-inSeparate
Custom DomainsYesYesYes

Pre-Deployment Checklist

Before deploying, ensure you've completed these steps:

1. Environment Variables

Create a .env.production template and verify all variables:

# Database
DATABASE_URL=postgresql://...

# Authentication
AUTH_SECRET=min-32-characters
AUTH_URL=https://yourdomain.com

# Stripe
STRIPE_SECRET_KEY=sk_live_...
STRIPE_WEBHOOK_SECRET=whsec_...
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_live_...

# Email
RESEND_API_KEY=re_...

# Monitoring
SENTRY_DSN=https://...

2. Build Verification

Test your production build locally:

# Build the application
pnpm build

# Start in production mode
pnpm start

# Verify all pages load correctly
# Test authentication flow
# Test Stripe checkout

3. Database Migration

Ensure migrations are ready:

# Generate migration from schema changes
pnpm prisma migrate dev

# Deploy migrations to production
pnpm prisma migrate deploy

Deploying to Vercel

Step 1: Connect Repository

  1. Go to vercel.com and sign in
  2. Click "Add New Project"
  3. Import your GitHub repository
  4. Vercel auto-detects Next.js settings

Step 2: Configure Environment Variables

Add your production environment variables:

# In Vercel Dashboard → Settings → Environment Variables
DATABASE_URL=postgresql://...
AUTH_SECRET=your-production-secret
STRIPE_SECRET_KEY=sk_live_...

Step 3: Configure Build Settings

For most Next.js apps, defaults work. For monorepos:

// vercel.json
{
  "buildCommand": "pnpm build",
  "outputDirectory": ".next",
  "installCommand": "pnpm install"
}

Step 4: Deploy

Push to your main branch to trigger deployment:

git push origin main

Step 5: Configure Domain

  1. Go to Project Settings → Domains
  2. Add your custom domain
  3. Update DNS records as instructed
  4. Wait for SSL certificate provisioning

Deploying to Railway

Step 1: Create Project

# Install Railway CLI
npm install -g @railway/cli

# Login
railway login

# Create new project
railway init

Step 2: Add Services

# Add PostgreSQL
railway add postgresql

# Link to your project
railway link

Step 3: Configure Environment

# Set environment variables
railway variables set DATABASE_URL=${{Postgres.DATABASE_URL}}
railway variables set AUTH_SECRET=your-secret
railway variables set STRIPE_SECRET_KEY=sk_live_...

Step 4: Deploy

# Deploy current directory
railway up

Step 5: Add Custom Domain

  1. Go to Railway Dashboard → Settings → Domains
  2. Add your domain
  3. Configure DNS CNAME record

Database Setup

Using Neon (Serverless Postgres)

Neon offers serverless PostgreSQL optimized for Next.js:

# 1. Create database at neon.tech
# 2. Get connection string
# 3. Add to environment variables

DATABASE_URL=postgresql://user:pass@ep-xxx.us-east-2.aws.neon.tech/neondb?sslmode=require

Configure connection pooling:

// lib/db.ts
import { PrismaClient } from '@prisma/client';

const globalForPrisma = globalThis as unknown as {
  prisma: PrismaClient | undefined;
};

export const db =
  globalForPrisma.prisma ??
  new PrismaClient({
    log: process.env.NODE_ENV === 'development' ? ['error', 'warn'] : ['error']
  });

if (process.env.NODE_ENV !== 'production') {
  globalForPrisma.prisma = db;
}

Using Supabase

Supabase provides PostgreSQL with additional features:

# Connection for Prisma
DATABASE_URL=postgresql://postgres:[PASSWORD]@db.[PROJECT].supabase.co:5432/postgres

# Connection pooling (recommended)
DATABASE_URL=postgresql://postgres:[PASSWORD]@db.[PROJECT].supabase.co:6543/postgres?pgbouncer=true

Setting Up CI/CD

GitHub Actions Pipeline

Create a comprehensive CI/CD pipeline:

# .github/workflows/ci.yml
name: CI/CD

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

env:
  DATABASE_URL: ${{ secrets.DATABASE_URL }}

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: pnpm/action-setup@v2
        with:
          version: 8
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'pnpm'
      - run: pnpm install
      - run: pnpm lint
      - run: pnpm typecheck

  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: pnpm/action-setup@v2
        with:
          version: 8
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'pnpm'
      - run: pnpm install
      - run: pnpm test

  build:
    runs-on: ubuntu-latest
    needs: [lint, test]
    steps:
      - uses: actions/checkout@v4
      - uses: pnpm/action-setup@v2
        with:
          version: 8
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'pnpm'
      - run: pnpm install
      - run: pnpm build

Monitoring and Observability

Setting Up Sentry

Add error tracking with Sentry:

pnpm add @sentry/nextjs
npx @sentry/wizard@latest -i nextjs

Configure Sentry:

// sentry.client.config.ts
import * as Sentry from '@sentry/nextjs';

Sentry.init({
  dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
  tracesSampleRate: 0.1,
  replaysSessionSampleRate: 0.1,
  replaysOnErrorSampleRate: 1.0,
  integrations: [
    Sentry.replayIntegration({
      maskAllText: true,
      blockAllMedia: true
    })
  ]
});

Setting Up Logging

Use structured logging with Pino:

// lib/logger.ts
import pino from 'pino';

export const logger = pino({
  level: process.env.LOG_LEVEL || 'info',
  transport:
    process.env.NODE_ENV === 'development'
      ? { target: 'pino-pretty' }
      : undefined,
  redact: ['password', 'token', 'authorization']
});

// Usage
logger.info({ userId, action: 'login' }, 'User logged in');
logger.error({ error, userId }, 'Payment failed');

Uptime Monitoring

Set up uptime monitoring with services like:

  • Better Uptime: Great free tier, incident management
  • Checkly: Synthetic monitoring, API checks
  • Vercel Analytics: Built-in if using Vercel

Production Checklist

Security

  • HTTPS enforced on all routes
  • Security headers configured (CSP, HSTS, etc.)
  • API rate limiting enabled
  • Sensitive data encrypted
  • Environment variables secured
  • Database connections use SSL

Performance

  • Images optimized (WebP, proper sizing)
  • Fonts preloaded
  • Critical CSS inlined
  • Bundle size analyzed
  • Caching headers configured
  • Edge functions for latency-sensitive routes

Reliability

  • Error tracking configured (Sentry)
  • Logging set up
  • Database backups automated
  • Uptime monitoring active
  • Alerting configured
  • Rollback strategy defined

Compliance

  • Privacy policy in place
  • Terms of service published
  • Cookie consent implemented
  • Data retention policy defined
  • GDPR/CCPA compliance if applicable

Post-Deployment

Monitor First 24 Hours

Watch for:

  • Error rates in Sentry
  • Performance metrics in hosting dashboard
  • Database connection issues
  • Failed authentication attempts
  • Stripe webhook failures

Set Up Alerts

Configure alerts for:

  • Error rate spikes
  • Response time degradation
  • Database connection failures
  • Payment failures
  • SSL certificate expiry

Document Runbooks

Create runbooks for common incidents:

## High Error Rate

1. Check Sentry for error details
2. Review recent deployments
3. Check database connectivity
4. Verify third-party API status
5. Rollback if necessary: `vercel rollback`

## Database Connection Issues

1. Check connection pool usage
2. Verify DATABASE_URL is correct
3. Check database provider status
4. Scale connection pool if needed

Scaling Considerations

As your SaaS grows, consider:

Database

  • Add read replicas for read-heavy workloads
  • Implement connection pooling (PgBouncer)
  • Consider caching layer (Redis)

Compute

  • Enable auto-scaling
  • Use edge functions for global latency
  • Consider dedicated instances for predictable workloads

CDN

  • Cache static assets aggressively
  • Use image CDN for user-uploaded content
  • Implement stale-while-revalidate patterns

Conclusion

Deploying a Next.js SaaS to production involves:

  1. Choosing the right platform based on your needs
  2. Proper configuration of environment and build settings
  3. Database setup with connection pooling
  4. CI/CD pipelines for reliable deployments
  5. Monitoring for visibility into production
  6. Ongoing maintenance and scaling

Start with Vercel or Railway for simplicity, and migrate to more complex setups as your needs grow. The most important thing is shipping—you can always optimize later.


Building a SaaS? Achromatic comes with deployment guides for Vercel, Railway, and Docker, plus built-in Sentry integration and production-ready configurations.