EmpireUI
Get Pro
← Blog9 min read#next.js#deployment#vercel

Deploying Next.js in 2026: Vercel, Docker, VPS Compared

Vercel, Docker, or a bare VPS? In 2026, the right Next.js deployment choice depends on your traffic, budget, and how much ops pain you're willing to accept.

Developer working on deployment pipeline on a laptop screen

The Deployment Landscape Hasn't Simplified — It's Exploded

Back in 2021, you basically had two choices: push to Vercel or figure out your own server. In 2026, the options range from fully managed platforms to bare metal with custom Docker orchestration, and picking wrong costs you real money or real dev hours. This guide cuts through the noise.

Here's the thing: Next.js 15 ships with the App Router stable, Partial Prerendering in production, and Server Actions that actually work under load. These features aren't equally supported across every host. Some platforms still treat RSC like a second-class citizen, and you'll feel it when cold starts blow past 800ms on a supposedly 'fast' edge network.

What you actually need to think about before choosing a deployment target: expected p99 latency, whether you need ISR or PPR, how your team handles on-call, and what your monthly bill looks like at 50k daily active users. Not sexy questions. But they'll save you a painful migration at 2am.

In practice, most teams under 10 engineers should default to Vercel, then graduate to Docker on a VPS when the bill hits $500/month or when you need custom infrastructure — not before.

Vercel: Still the Path of Least Resistance

Vercel wrote Next.js. That's worth saying plainly. Their platform supports every Next.js feature on day one, often before the docs catch up. PPR, Edge Runtime, Fluid Compute — if it lands in the framework, Vercel supports it immediately. No waiting for third-party adapters to catch up.

The developer experience is genuinely hard to beat. Push to a branch and you get a preview URL in under 90 seconds. PR comments show the deployment link automatically. Rolling back is one click. For a team shipping fast with limited ops bandwidth, this stuff adds up to meaningful time savings every week.

That said, the cost model bites you at scale. The Pro plan starts at $20/month per seat, but bandwidth and function invocations can balloon your bill fast. Honestly, if you're running an e-commerce site doing 200k requests/day with heavy ISR, you should run the numbers carefully before committing. The Vercel pricing calculator isn't always your friend.

Worth noting: Vercel now caches aggressively by default in Next.js 15. If you haven't audited your fetch calls with proper cache and next.revalidate options, you'll get stale data in production and spend hours confused about why. Check the Next.js caching strategies breakdown for a solid mental model before you deploy anything serious.

For most apps serving the US market with under 1M monthly page views, Vercel is still the right answer. Don't over-engineer it.

Docker: Full Control, Full Responsibility

Docker gives you a reproducible, portable build artifact that runs identically in dev, staging, and prod. That's the pitch. The reality is you now own the networking, the reverse proxy config, the SSL renewal, the health checks, and the rollback strategy. None of that is free.

Next.js has a first-class output: 'standalone' mode that produces a minimal Node.js build, stripping out everything you don't need. Your final Docker image can be around 150–200MB depending on your dependencies. Here's the Dockerfile pattern that actually works in 2026:

FROM node:22-alpine AS base

# Install dependencies
FROM base AS deps
WORKDIR /app
COPY package.json yarn.lock ./
RUN yarn install --frozen-lockfile

# Build
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN yarn build

# Runner
FROM base AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY --from=builder /app/public ./public
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static

EXPOSE 3000
CMD ["node", "server.js"]

One more thing — the standalone output doesn't include your public folder or .next/static. You have to copy those explicitly, which trips up almost everyone the first time. The Docker build will succeed. The app will look broken in prod. Copy those two directories.

Quick aside: if you're building a UI-heavy project with custom components from Empire UI, make sure your CSS extraction and font loading are sorted before containerizing. Static assets in Docker need proper cache headers on the reverse proxy level, or your 400px glassmorphism cards will cause a layout flash on every page load.

For teams who want Docker but don't want to babysit the orchestration layer themselves, Dokploy is worth a look. It's a self-hosted PaaS that sits on top of Docker Swarm, handles the reverse proxy and SSL, and gives you a UI that actually works. If you've already got a VPS, it shaves hours off setup.

VPS Deployment: When to Go Bare Metal

A $20/month Hetzner VPS (8GB RAM, 4 vCPU) can comfortably serve 50k daily users on a well-optimized Next.js app. Vercel at that scale would run you $200–400/month or more depending on bandwidth. The math is hard to argue with, especially for bootstrapped projects or internal tools.

The workflow looks like this: you build your Docker image in CI, push it to a registry (GHCR, Docker Hub, or your own), then your VPS pulls and redeploys. Traefik or Nginx sits in front handling SSL via Let's Encrypt and routing traffic to the container. Health checks keep bad deploys from going live.

# docker-compose.yml
version: '3.8'
services:
  web:
    image: ghcr.io/yourorg/yourapp:latest
    restart: unless-stopped
    environment:
      - NODE_ENV=production
      - DATABASE_URL=${DATABASE_URL}
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.web.rule=Host(`yourdomain.com`)"
      - "traefik.http.routers.web.tls.certresolver=letsencrypt"
    networks:
      - traefik-network

networks:
  traefik-network:
    external: true

Look, the trade-off is real. You're now responsible for patching the OS, monitoring disk space, handling Node.js process crashes, and making sure your Let's Encrypt certificates renew. If your team doesn't have anyone comfortable with Linux sysadmin work, a VPS is going to cause pain at the worst possible times — like during a traffic spike on a Friday afternoon.

That said, once you've got the setup working, it's remarkably stable. Teams have been running this pattern since at least 2019 and it holds up fine. The key is good monitoring (Uptime Kuma is free and does the job) and automated deployments through CI so nobody is SSHing in manually.

ISR, Edge Functions, and PPR: What Actually Works Where

This is where platform differences bite you hardest. Incremental Static Regeneration with revalidate timers works everywhere that runs Node.js — Vercel, Docker on a VPS, Railway, Render. But PPR (Partial Prerendering, stable since Next.js 15.1) currently only has full support on Vercel. On other platforms it degrades gracefully, but you lose the Suspense-boundary streaming optimization.

Edge Runtime is another landmine. If you've got middleware or API routes using export const runtime = 'edge', those need a V8 isolate environment. Vercel, Cloudflare, and Netlify support this. Your Docker container running Node.js does not — it'll throw at startup. Check every route file before you migrate.

// This breaks on Node.js runtimes — Edge only
export const runtime = 'edge'

export async function GET(request: Request) {
  // Works fine on Vercel/CF, crashes on Docker/VPS
  return new Response('hello')
}

Server Actions work fine everywhere as long as you're running Node.js 18+. The Docker image in the previous section uses Node 22, which is the right call. Node 18 goes EOL in April 2025, and you don't want to be scrambling to upgrade in the middle of a prod incident.

One more thing — if you're using the Next.js App Router heavily with layouts and nested Suspense boundaries, test your real loading behavior on the actual deployment target. Vercel's edge network might be masking slow cold starts that only show up when you move to a single-region VPS with 512MB containers.

CI/CD Pipelines That Don't Suck

Regardless of which deployment target you pick, you need automated deploys. Manually pushing to prod is how outages happen and how you train your team to cut corners. The pipeline should be boring: test, build, deploy, notify.

For Vercel, the CI story is basically automatic — connect your GitHub repo and it handles preview and production deploys without you touching anything. You can override with custom build commands in vercel.json if your monorepo structure needs it.

For Docker targets, here's a GitHub Actions workflow that builds, pushes to GHCR, and SSH deploys to a VPS:

name: Deploy
on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Build and push Docker image
        run: |
          echo ${{ secrets.GHCR_TOKEN }} | docker login ghcr.io -u ${{ github.actor }} --password-stdin
          docker build -t ghcr.io/${{ github.repository }}:latest .
          docker push ghcr.io/${{ github.repository }}:latest

      - name: Deploy to VPS
        uses: appleboy/ssh-action@v1
        with:
          host: ${{ secrets.VPS_HOST }}
          username: deploy
          key: ${{ secrets.VPS_KEY }}
          script: |
            docker pull ghcr.io/${{ github.repository }}:latest
            docker compose up -d --no-deps web

Keep deployment keys scoped. That deploy user on your VPS should only have permission to run docker commands, not sudo access. It's a small thing that matters a lot if your CI ever gets compromised.

Worth noting: build times matter more than most teams realize. A 4-minute Docker build on every PR means devs start ignoring CI feedback. Cache your node_modules layer aggressively, and consider using Turborepo's remote cache if you're in a monorepo — it can cut build time from 4 minutes down to under 60 seconds on cache hits.

The Decision Matrix: Which Platform Is Right for You

Stop overthinking it. Here's the honest breakdown based on what actually matters.

Pick Vercel if: you're a small team (under 5 engineers), your monthly traffic is under 1M requests, you want zero ops overhead, and you're using cutting-edge Next.js features like PPR or Edge Middleware. The $20/month Pro plan is worth it just for the zero-config SSL and global CDN. You can always migrate later.

Pick Docker on a VPS if: your Vercel bill has crossed $300/month, you need co-location with a database or other internal services on the same network, or your company has compliance requirements that prevent data leaving specific regions. Budget a day or two for the initial setup — it's not hard, just time-consuming.

Pick a managed PaaS (Railway, Render, Fly.io) if: you want something between Vercel and a bare VPS. These platforms take Docker images and handle the ops layer for you at prices between Vercel and raw VPS costs. Railway in particular has gotten solid in 2025–2026 and their free tier is genuinely useful for side projects.

Honestly, the worst move is picking a deployment platform based on a blog post (including this one) without running your actual numbers. Spin up a staging environment on your target platform, run a load test, watch the metrics, then decide. For UI-heavy Next.js apps with lots of components — if you're using Empire UI for your design system — the main variables are font loading, CSS bundle size, and image optimization, not which cloud you're on.

Whatever you pick, check out Next.js Server Actions and Next.js middleware patterns — both have deployment-specific gotchas worth knowing before you ship.

FAQ

Can I deploy a Next.js app with App Router to a regular VPS?

Yes, as long as you're running Node.js 18+. Use output: 'standalone' in your next.config.js and containerize with Docker. Edge Runtime routes won't work — replace those with Node.js runtime equivalents before migrating.

Does Vercel still make sense in 2026 if you're paying $400/month?

At that spend, do the math against a $40/month Hetzner VPS plus 2–4 days of migration work. If your team lacks ops experience, the Vercel cost might still win. If you have a DevOps-comfortable engineer, move to Docker on a VPS.

What's the fastest way to deploy a Next.js app right now?

Push to GitHub, connect to Vercel, done. Under 5 minutes from zero to production URL. For anything requiring custom infra, Docker Compose on a VPS with Traefik is the next fastest proven pattern.

Does PPR (Partial Prerendering) work outside Vercel?

Partial Prerendering is stable in Next.js 15.1 but full streaming support currently requires Vercel's infrastructure. On other platforms it falls back to standard SSR — your app still works, just without the Suspense-boundary optimization.

Free components in 40 styles
React & Tailwind, copy-paste ready.
Browse →

Read next

Next.js OG Image Generation: @vercel/og, Edge Runtime, Custom FontsAnalytics in Next.js: Vercel Analytics, PostHog, Plausible SetupEdge Runtime in Next.js: Middleware, Edge API Routes and LimitsDocker + Next.js Production Setup: Multi-Stage Build, Alpine, Env