codingstairs
NotesEDULifeContact
⌕Search⌘K
koen

Navigation

  • Intro
  • Blog
  • Life

Get in touch

Send without signing in. Add your email if you'd like a reply.

  • Leave a message anonymously →
  • ✉ warragon112@gmail.com
  • KakaoTalk Open Chat ↗

© 2026 codingstairs

  • Notes
  • EDU
  • Search
  • Life
  • Contact
  • Legal
  • RSS
  • GitHub
EDU›Build Your First Fullstack App with Next.js 16›Step 4

Step 4

Step 4 — Deploy (Vercel · Fly.io · Docker)

0 views

Step 4 — Deploy (Vercel · Fly.io · Docker)

Three practical paths for a Next.js fullstack.

1. Three options

Path Pros Cons
Vercel easiest · git-push deploy · free tier serverless limits · long tasks hard
Fly.io Dockerfile as-is · Postgres included · always-on slightly more setup
Self-host + Docker + Caddy full control · cheapest ops overhead

Beginners → Vercel. Intermediate → Fly.io. Educational → self-host.

2. Vercel

  1. Sign up at vercel.com
  2. Add New... → Project
  3. Pick the GitHub repo
  4. Framework auto-detects Next.js
  5. Set env vars (DATABASE_URL etc.)
  6. Deploy

Main push → auto redeploy. PRs get preview URLs.

Limits: 10s function timeout (Pro 60s / Enterprise 900s), serverless only, external Postgres (Neon / Supabase).

3. Fly.io — Docker-based

standalone build

next.config.ts:

import type { NextConfig } from "next";
const config: NextConfig = { output: "standalone" };
export default config;

Dockerfile

FROM node:20-alpine AS base
RUN corepack enable && corepack prepare pnpm@10.33.0 --activate

FROM base AS deps
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile

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

FROM base AS runner
WORKDIR /app
ENV NODE_ENV=production ENV PORT=3000
COPY --from=builder /app/public ./public
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
USER node
EXPOSE 3000
CMD ["node", "server.js"]

.dockerignore:

node_modules
.next
.git
.env.local
Dockerfile
README.md

CLI

brew install flyctl     # or winget install flyctl

fly auth signup
fly launch
fly postgres create
fly postgres attach <app-name>
fly deploy

Live at https://<app>.fly.dev.

Handy commands

fly status
fly logs
fly ssh console
fly secrets set KEY=VALUE
fly scale count 2

4. Self-host + Caddy

docker-compose.yml:

services:
  web:
    build: .
    env_file: .env.prod
    ports: ["127.0.0.1:3000:3000"]
    depends_on: [postgres]

  postgres:
    image: postgres:16-alpine
    environment:
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_DB: my_app
    volumes: [pg-data:/var/lib/postgresql/data]
    ports: ["127.0.0.1:5432:5432"]

  caddy:
    image: caddy:2-alpine
    ports: ["80:80", "443:443"]
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - caddy-data:/data

volumes:
  pg-data:
  caddy-data:

Caddyfile:

example.com {
  reverse_proxy web:3000
}

Deploy:

scp -r . user@server:/opt/my-fullstack
ssh user@server
cd /opt/my-fullstack
docker compose up -d

5. Env var separation

Var Purpose
DATABASE_URL production DB
NEXT_PUBLIC_SITE_URL client-exposed URL
NEXTAUTH_SECRET / JWT_SECRET session
STRIPE_*, RESEND_* external APIs

Vercel → Dashboard · Fly.io → fly secrets · self-host → .env.prod.

6. Custom domain

Vercel and Fly.io both support custom domains. DuckDNS works fine for learning.

7. HTTPS

  • Vercel / Fly.io — automatic
  • Caddy — automatic
  • Nginx + certbot — manual

Don't run without HTTPS; cookies and OAuth often require it.

8. Observability

fly logs
vercel logs
docker compose logs -f web

Add Sentry when errors stick.

9. CI/CD

name: deploy
on: { push: { branches: [main] } }
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: superfly/flyctl-actions/setup-flyctl@master
      - run: flyctl deploy --remote-only
        env: { FLY_API_TOKEN: "${{ secrets.FLY_API_TOKEN }}" }

Vercel auto-deploys via git integration.

10. Gotchas

  • Build fails for missing env — check build-time vs runtime
  • Migrations not applied — fly ssh console and run pnpm drizzle-kit migrate
  • Image too large — check output: "standalone" and .dockerignore
  • HTTPS cert failure — DNS must resolve first; Caddy needs port 80 open

11. Costs

Option Free Paid
Vercel Hobby (personal, non-commercial) $20/mo Pro
Fly.io $5 credit / small apps per-instance billing
VPS none $4–10/mo (Hetzner)

12. Post-deploy checklist

  • /api/health and home 200
  • Valid HTTPS cert
  • DB migrations applied
  • No missing env
  • Logging / error monitoring set
  • Production secrets separated from test

Closing

A successful first deployment is a milestone. Start on Vercel in 5 minutes, graduate to Fly.io or self-host. Code that's actually deployed is code you've actually learned.

🎉 Fullstack cycle complete.

Next

  • devops-cloud or security-foundations

References: Vercel · Fly.io · Caddy.

← Step 3

Step 3 — API Route + Drizzle ORM

🎉 You finished Build Your First Fullstack App with Next.js 16

What's next? Pick another course below.

Next: Backend with Spring Boot 4 →Browse all courses