Back to Blog
Tutorial10 min read2026-06-29

How to Deploy a Blitz.js App to Production

Blitz.js layers a zero-API data layer and auth onto Next.js, so deploying it is deploying Next.js with a few Blitz-specific steps. This guide covers the build, Prisma migrations, session secrets, and going live.

Ajay Kumar
Ajay Kumar
Founder & DevOps, PandaStack

Blitz.js is a full-stack toolkit that sits on top of Next.js, adding a "zero-API" data layer (call server queries/mutations directly from React), built-in authentication, and Prisma integration. Because it builds on Next.js, deploying Blitz is deploying a Next.js app — with a handful of Blitz-specific concerns around Prisma and session secrets.

What Blitz adds on top of Next.js

  • Queries & mutations — server functions you import directly into components; Blitz handles the RPC.
  • Auth — a session layer with secure, httpOnly cookies out of the box.
  • Prisma — wired in by default for the database.

The build and run commands are the familiar Next.js ones, exposed through the Blitz CLI:

blitz build    # production build
blitz start    # production server (PORT 3000 by default)

Prisma migrations

Blitz uses Prisma, so production migrations follow the standard migrate deploy pattern:

# Development: create a migration
blitz prisma migrate dev --name add_projects

# Production: apply committed migrations
blitz prisma migrate deploy

Run migrate deploy as a deploy step before the new version serves traffic. Point Prisma at your database via DATABASE_URL:

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

Don't forget blitz prisma generate runs as part of the build to produce the client — Blitz wires this into blitz build, but if you customize the pipeline, ensure the client is generated before blitz start.

Session secret

Blitz's auth signs sessions with a secret. In production you must provide a strong, stable value:

SESSION_SECRET_KEY=$(openssl rand -hex 32)

Set it as an environment variable. If it changes, all existing sessions are invalidated, so keep it constant per environment. This is the single most common Blitz production mistake — forgetting to set a stable SESSION_SECRET_KEY and getting logged-out users after every deploy.

A production Dockerfile

FROM node:20-slim AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npx blitz build

FROM node:20-slim
WORKDIR /app
COPY --from=build /app ./
ENV NODE_ENV=production
EXPOSE 3000
CMD ["npx", "blitz", "start"]

Because Blitz is Next.js underneath, you can also lean on Next's standalone output mode for a smaller image if you configure it — but the straightforward Dockerfile above works everywhere.

Deploying on PandaStack

  1. 1Provision a managed PostgreSQL (14.x or 16.x). PandaStack injects DATABASE_URL; Prisma reads it directly.
  2. 2Connect the Git repo as a container app. The Dockerfile is auto-detected; without one, the Node buildpack runs blitz build / blitz start.
  3. 3Set SESSION_SECRET_KEY, NODE_ENV=production, and any auth provider secrets.
  4. 4Run npx blitz prisma migrate deploy once before exposing traffic.
  5. 5Add a custom domain; SSL is automatic.

Because deploys are git-push and the platform keeps deploy history, a bad migration is recoverable: roll back the app version while you reconcile the schema.

Production checklist

  • [ ] Stable SESSION_SECRET_KEY (>=32 bytes).
  • [ ] prisma migrate deploy as a deploy step, not auto-migrate.
  • [ ] Prisma client generated during build.
  • [ ] NODE_ENV=production.
  • [ ] Connection pool sized to the DB instance (Prisma's default pool can be tuned via the connection string connection_limit).
  • [ ] Auth provider redirect URLs point at the production domain.

A pooling note for Prisma

Prisma opens a connection pool per instance. With multiple replicas you can exhaust a small database's connection limit. Cap it in the URL:

postgresql://user:pass@host:5432/db?connection_limit=10

Keep total connections across all replicas under your database tier's max.

Verifying

# App responds
curl -s -o /dev/null -w '%{http_code}' https://app.example.com/

# An RPC endpoint exists under /api/rpc/* once you have queries

A 200 on the root and working authenticated routes confirm the deploy.

References

  • [Blitz.js documentation](https://blitzjs.com/docs/get-started)
  • [Blitz CLI reference](https://blitzjs.com/docs/cli-overview)
  • [Blitz authentication / session management](https://blitzjs.com/docs/session-management)
  • [Prisma migrate deploy](https://www.prisma.io/docs/orm/prisma-migrate/workflows/development-and-production)

---

Blitz is a Next.js app at heart, which makes it a clean PandaStack container deploy with a managed PostgreSQL and DATABASE_URL injected. Start free at [dashboard.pandastack.io](https://dashboard.pandastack.io).

Ready to deploy?

Start free on PandaStack.

Start free on PandaStack

More in Tutorial

Browse all Tutorial articles →

See also