Skip to content

Deployment

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.

Package/runtimeUse it forDo not use it for
@jsorm/runtime + @jsorm/fetchEdge-safe request handlers and fetch-based SQL accessOwning migrations or jsorm deploy
@jsorm/core / @jsorm/node + native adaptersNode services, release jobs, direct database accessEdge isolates without TCP/native binary support
@jsorm/nodeCLI, migrations, jsorm deploy, release automationEdge 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.

Terminal window
jsorm deploy [selector] [--dry-run] [--verbose] [--strict] [--force]

jsorm deploy:

  1. validates connectivity
  2. checks applied migration hashes/checksums
  3. inspects pending migrations for unsafe changes
  4. verifies schema snapshot integrity before execution
  5. applies pending migrations, or previews them with --dry-run
  6. verifies schema snapshot integrity again after execution

When jsorm.config.ts defines a default migration source, selector mode is optional:

Terminal window
pnpm exec jsorm deploy --strict --verbose
pnpm exec jsorm deploy main --strict
FlagMeaningTypical use
--dry-runPreview pending deploy plan without mutating migration historyCI validation and pre-release review
--verbosePrint issues and compiled SQL statementsRelease logs and troubleshooting
--strictFail on warnings, snapshot drift, or review-required changesDefault for CI and production
--forceAllow destructive migrations that are blocked by defaultOnly after explicit review

jsorm deploy is designed for CI/CD decisions:

Exit codeMeaningCI interpretation
0SuccessPromote release
2Usage/CLI errorFix command/config
3Connectivity/preflight failureRetry infra or secrets setup
4Integrity failureStop release and investigate drift/checksums
5Unsafe deploy blockedRequire review or --force
6Execution/verification failureStop rollout and inspect database state

Recommended release commands:

Terminal window
# preview in CI
pnpm exec jsorm deploy --dry-run --strict --verbose
# production release
pnpm exec jsorm deploy --strict --verbose
  1. Build artifacts.
  2. Run jsorm deploy --dry-run --strict --verbose in CI.
  3. Run jsorm deploy --strict --verbose in the release job.
  4. Only then promote the new app version.

This keeps migration ownership in Node, keeps edge bundles minimal, and gives CI explicit failure signals.

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 }}
  • Node runtime: use @jsorm/core or @jsorm/node with native adapters and pin handlers when needed:
export const runtime = 'nodejs';
  • Edge runtime: use @jsorm/runtime + @jsorm/fetch in the app bundle.
  • Run pnpm exec jsorm deploy --strict --verbose in GitHub Actions or another Node release step, not inside the edge function.
  • Use @jsorm/runtime + @jsorm/fetch for request-time access.
  • Run deploy separately from a Node job before publishing the Worker.
Terminal window
pnpm exec jsorm deploy --strict --verbose
pnpm exec wrangler deploy

Run deploy before app startup, or move it into a one-off init container:

FROM node:24-alpine AS build
WORKDIR /app
COPY . .
RUN corepack enable && pnpm install --frozen-lockfile && pnpm run build
FROM node:24-alpine
WORKDIR /app
COPY --from=build /app ./
RUN corepack enable
CMD ["sh", "-c", "pnpm exec jsorm deploy --strict --verbose && pnpm start"]

Use a Node deploy job with @jsorm/pg against the Postgres connection string:

Terminal window
pnpm exec jsorm deploy main --strict --verbose

If 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/fetch when you expose HTTP SQL access
Terminal window
pnpm exec jsorm deploy --strict --verbose

Use a Node deploy job with @jsorm/mysql:

Terminal window
pnpm exec jsorm deploy main --strict --verbose

For edge request traffic, keep a separate HTTP/fetch access path. Do not expect the native MySQL adapter to run inside edge isolates.