Deployment
Production deploy workflow
Section titled “Production deploy workflow”Use jsorm deploy as the production-safe migration entrypoint. Keep request-time runtime code separate from schema ownership, and run deploys from a controlled Node.js environment.
Deployment ownership
Section titled “Deployment ownership”| Package/runtime | Use it for | Do not use it for |
|---|---|---|
@jsorm/runtime + @jsorm/fetch | Edge-safe request handlers and fetch-based SQL access | Owning migrations or jsorm deploy |
@jsorm/core / @jsorm/node + native adapters | Node services, release jobs, direct database access | Edge isolates without TCP/native binary support |
@jsorm/node | CLI, migrations, jsorm deploy, release automation | Edge request handling |
jsorm deploy is intentionally Node-only deployment ownership. Even if the app runs on Vercel Edge or Cloudflare Workers, deploys should run in CI, a release job, or a dedicated container with @jsorm/node.
What jsorm deploy does
Section titled “What jsorm deploy does”jsorm deploy [selector] [--dry-run] [--verbose] [--strict] [--force]jsorm deploy:
- validates connectivity
- checks applied migration hashes/checksums
- inspects pending migrations for unsafe changes
- verifies schema snapshot integrity before execution
- applies pending migrations, or previews them with
--dry-run - verifies schema snapshot integrity again after execution
When jsorm.config.ts defines a default migration source, selector mode is optional:
pnpm exec jsorm deploy --strict --verbosepnpm exec jsorm deploy main --strict| Flag | Meaning | Typical use |
|---|---|---|
--dry-run | Preview pending deploy plan without mutating migration history | CI validation and pre-release review |
--verbose | Print issues and compiled SQL statements | Release logs and troubleshooting |
--strict | Fail on warnings, snapshot drift, or review-required changes | Default for CI and production |
--force | Allow destructive migrations that are blocked by default | Only after explicit review |
Exit codes and CI intent
Section titled “Exit codes and CI intent”jsorm deploy is designed for CI/CD decisions:
| Exit code | Meaning | CI interpretation |
|---|---|---|
0 | Success | Promote release |
2 | Usage/CLI error | Fix command/config |
3 | Connectivity/preflight failure | Retry infra or secrets setup |
4 | Integrity failure | Stop release and investigate drift/checksums |
5 | Unsafe deploy blocked | Require review or --force |
6 | Execution/verification failure | Stop rollout and inspect database state |
Recommended release commands:
# preview in CIpnpm exec jsorm deploy --dry-run --strict --verbose
# production releasepnpm exec jsorm deploy --strict --verboseRecommended production flow
Section titled “Recommended production flow”- Build artifacts.
- Run
jsorm deploy --dry-run --strict --verbosein CI. - Run
jsorm deploy --strict --verbosein the release job. - Only then promote the new app version.
This keeps migration ownership in Node, keeps edge bundles minimal, and gives CI explicit failure signals.
Deployment examples
Section titled “Deployment examples”GitHub Actions
Section titled “GitHub Actions”name: deploy
on: push: branches: [main] workflow_dispatch:
jobs: migrate: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: pnpm/action-setup@v4 with: version: 11 - uses: actions/setup-node@v4 with: node-version: 24 cache: pnpm - run: pnpm install --frozen-lockfile - run: pnpm run build - run: pnpm exec jsorm deploy --strict --verbose env: DATABASE_URL: ${{ secrets.DATABASE_URL }}Vercel
Section titled “Vercel”- Node runtime: use
@jsorm/coreor@jsorm/nodewith native adapters and pin handlers when needed:
export const runtime = 'nodejs';- Edge runtime: use
@jsorm/runtime+@jsorm/fetchin the app bundle. - Run
pnpm exec jsorm deploy --strict --verbosein GitHub Actions or another Node release step, not inside the edge function.
Cloudflare Workers
Section titled “Cloudflare Workers”- Use
@jsorm/runtime+@jsorm/fetchfor request-time access. - Run deploy separately from a Node job before publishing the Worker.
pnpm exec jsorm deploy --strict --verbosepnpm exec wrangler deployDocker
Section titled “Docker”Run deploy before app startup, or move it into a one-off init container:
FROM node:24-alpine AS buildWORKDIR /appCOPY . .RUN corepack enable && pnpm install --frozen-lockfile && pnpm run build
FROM node:24-alpineWORKDIR /appCOPY --from=build /app ./RUN corepack enableCMD ["sh", "-c", "pnpm exec jsorm deploy --strict --verbose && pnpm start"]Supabase
Section titled “Supabase”Use a Node deploy job with @jsorm/pg against the Postgres connection string:
pnpm exec jsorm deploy main --strict --verboseIf the app runtime is edge-only, keep runtime traffic on @jsorm/runtime + @jsorm/fetch, but keep deploy on Node.
- Deploy/migrations: Node job +
@jsorm/pg - Edge request path:
@jsorm/runtime+@jsorm/fetchwhen you expose HTTP SQL access
pnpm exec jsorm deploy --strict --verbosePlanetScale
Section titled “PlanetScale”Use a Node deploy job with @jsorm/mysql:
pnpm exec jsorm deploy main --strict --verboseFor edge request traffic, keep a separate HTTP/fetch access path. Do not expect the native MySQL adapter to run inside edge isolates.