Runtimes
Choose packages by runtime boundary
Section titled “Choose packages by runtime boundary”jsorm separates authoring APIs, runtime-safe imports, CLI ownership, and database transport so each environment gets only what it can safely run.
Package selection at a glance
Section titled “Package selection at a glance”| Package | Use it for | Do not use it for |
|---|---|---|
@jsorm/core | Main authoring package for models, queries, config types, and migration primitives in Node-capable apps | Edge bundles that cannot use Node APIs or native binaries |
@jsorm/runtime | Universal or edge-safe application code, plus direct config injection when filesystem access is unavailable | Owning the jsorm CLI |
@jsorm/node | Tooling and runtime package for Node and Bun. On Node it provides the Rust engine bridge and native adapter plumbing for migrations and deploy workflows. On Bun it detects Bun config and uses Bun native DB APIs directly (no Rust engine) | CLI ownership or edge request handlers |
@jsorm/fetch | HTTP/fetch database transport for runtimes without TCP sockets or native binaries | Migration ownership or jsorm deploy |
@jsorm/pg, @jsorm/mysql, @jsorm/sqlite | Native adapters for direct database access from Node | Edge runtimes without raw TCP access |
Recommended combinations
Section titled “Recommended combinations”- Node app runtime:
@jsorm/coreor@jsorm/nodewith a native adapter package - Bun runtime:
@jsorm/node— detects Bun and uses Bun native database APIs directly, no Rust engine - Edge runtime:
@jsorm/runtimewith@jsorm/fetch - CI, release, and deploy jobs:
@jsorm/core+@jsorm/nodein a Node 24+ environment
Environment guide
Section titled “Environment guide”Node services and workers
Section titled “Node services and workers”Use native adapters when your runtime can open direct database connections and run Node APIs.
pnpm add @jsorm/core @jsorm/node @jsorm/pg pgimport { createJsorm, defineConnectionSource, defineJsormConfig } from '@jsorm/core';import { pgAdapter } from '@jsorm/pg';
const main = defineConnectionSource({ adapter: pgAdapter({ name: 'main', connectionString: process.env.DATABASE_URL!, }),});
const config = defineJsormConfig({ connectionSources: { main }, defaults: { connectionSource: 'main' },});
export const db = await createJsorm().init(config);Use this shape for long-lived servers, background workers, and containerized Node apps.
Bun services and scripts
Section titled “Bun services and scripts”Use @jsorm/node on Bun. The package detects the Bun runtime and uses Bun’s built-in SQLite, MySQL-compatible, and PostgreSQL-compatible APIs directly — bypassing the Rust engine entirely.
pnpm add @jsorm/core @jsorm/node @jsorm/pg pgimport { createJsorm, defineConnectionSource, defineJsormConfig } from '@jsorm/core';import { pgAdapter } from '@jsorm/pg';
const main = defineConnectionSource({ adapter: pgAdapter({ name: 'main', connectionString: process.env.DATABASE_URL!, }),});
const config = defineJsormConfig({ connectionSources: { main }, defaults: { connectionSource: 'main' },});
export const db = await createJsorm().init(config);On Bun, adapter calls go through Bun’s native database bindings instead of the Rust worker. The query API, type inference, and config shape are identical to Node.
Edge and fetch-only runtimes
Section titled “Edge and fetch-only runtimes”Use runtime-safe imports plus @jsorm/fetch when the request runtime cannot use raw TCP sockets or native binaries.
pnpm add @jsorm/runtime @jsorm/fetchpnpm add -D @jsorm/nodeimport { createJsorm, defineConnectionSource, defineJsormConfig } from '@jsorm/runtime';import { fetchAdapter } from '@jsorm/fetch';
const main = defineConnectionSource({ adapter: fetchAdapter({ name: 'main', dialect: 'postgres', endpoint: process.env.SQL_HTTP_ENDPOINT!, headers: () => ({ authorization: `Bearer ${process.env.SQL_HTTP_TOKEN!}`, }), }),});
const config = defineJsormConfig({ connectionSources: { main }, defaults: { connectionSource: 'main' },});
export const db = await createJsorm().init(config);This is the recommended path for Vercel Edge, Cloudflare Workers, and other fetch-only runtimes.
CI and deploy workflows
Section titled “CI and deploy workflows”Run migration and deploy commands from Node, even if the application itself runs at the edge.
pnpm exec jsorm deploy --strict --verboseTypical places to run this:
- GitHub Actions
- a release container or init job
- a dedicated Node deployment step before rollout
Quick decision matrix
Section titled “Quick decision matrix”| Environment | Runtime package | Transport | Migration/deploy owner |
|---|---|---|---|
| Node API/server | @jsorm/core or @jsorm/node | native adapter | same Node runtime or CI job |
| Bun service / script | @jsorm/node | Bun native API | same Bun runtime or CI job (Node) |
| Vercel Edge / Workers | @jsorm/runtime | @jsorm/fetch | separate @jsorm/core + @jsorm/node job |
| CI / release pipeline | @jsorm/core + @jsorm/node | native adapter | @jsorm/core + @jsorm/node |
Engine mode and workers
Section titled “Engine mode and workers”jsorm uses a persistent worker process by default in Node runtimes to eliminate per-query spawn overhead. When engine.mode is omitted in jsorm.config.ts, it defaults to "worker".
// jsorm.config.tsexport default defineJsormConfig({ engine: { // mode defaults to "worker" worker: { startupTimeoutMs: 5_000, requestTimeoutMs: 10_000, restartLimit: 3, }, },});You can fall back to legacy per-query execution by explicitly setting engine.mode: "spawn" if needed. Note that worker mode is Node.js runtime only — on Bun, @jsorm/node bypasses the Rust engine entirely and uses Bun’s native database APIs.
Shared resources and isolation
Section titled “Shared resources and isolation”Runtimes in the same Node process share adapter pools and Rust worker processes when their effective configuration fingerprint matches.
createJsorm(): Standard instances automatically participate in the shared-resource registry. This avoids recreating DB connection pools across repeated imports.createJsormTest(): Sandboxed instances for testing intentionally disable filesystem config discovery and isolate their resources by default, preventing tests from trampling on each other’s pools.
import { createJsorm, createJsormTest } from '@jsorm/core';
// Reuses shared worker and connection pools based on config fingerprintconst appDb = await createJsorm().init();
// Uses isolated resources by defaultconst testDb = await createJsormTest().init();Native adapters
Section titled “Native adapters”Choose the adapter package that matches your database:
- PostgreSQL →
@jsorm/pg - MySQL / PlanetScale →
@jsorm/mysql - SQLite →
@jsorm/sqlite
Install only the adapter packages you actually use. The core packages do not bundle database drivers by default.
Best practices
Section titled “Best practices”- Keep app/runtime imports and CLI ownership separated.
- Use native adapters in Node, and
@jsorm/fetchonly for fetch-only runtimes. - On Bun,
@jsorm/nodedetects the runtime automatically — the same package works for both Node and Bun. - Run
jsorm deployoutside edge functions. - Treat CI and release jobs as Node environments with full migration responsibility.