Typed SQL runtime

SQL-first ORM runtime for TypeScript and PostgreSQL.

OBJX combines typed models, SQL compilation, execution context, graph operations, and PostgreSQL-oriented runtime APIs in one runtime. SQLite and MySQL remain supported through official drivers.

  • PostgreSQL runtime APIs: queue, outbox, cache, search, vector, JSONB, and RLS
  • Graph operations: insertGraph, upsertGraph, relate, and unrelate
  • ExecutionContext, nested transactions, and predictable hydration paths
  • Official drivers for PostgreSQL, SQLite, and MySQL
  • Codegen, migrations, seeds, validation, NestJS, and fullstack adapters
Packages 10

Core runtime, drivers, plugins, validation, codegen, and framework adapters.

Dialects 3

PostgreSQL, SQLite, and MySQL with official support.

Focus Predictable SQL

Typed query building, explicit runtime behavior, and database-aware extensions.

PostgreSQL runtime surface

SQL-native application primitives on top of one runtime.

OBJX exposes PostgreSQL-specific capabilities as typed runtime APIs while keeping execution context, transaction control, and query composition explicit.

Database primitives Queue, outbox, cache, search, vector, and RLS
Runtime contracts ExecutionContext, transactions, hydration, and plugins
Operational path Codegen, examples, benchmarks, NestJS, and fullstack adapters

Postgres runtime APIs

  • Queue: SKIP LOCKED workers, retry/backoff, DLQ.
  • Events: transactional outbox + LISTEN/NOTIFY fanout.
  • Search: tsvector/tsquery rank + highlights.
  • Vector: pgvector similarity + relational filters.

Operational contracts

  • Internal schema provisioning with migration registry.
  • ExecutionContext-aware runtime requests.
  • Background worker handles with graceful control.
  • Built-in runtime metrics and query linting hooks.

Dialect support

SQLite and MySQL remain supported through official drivers. PostgreSQL receives the deeper runtime surface and the broadest set of SQL-native extensions.

PostgreSQL · Primary SQLite · Supported MySQL · Supported

Benchmark

Checked-in benchmark data, not synthetic claims.

These charts are generated from the benchmark suite in the repository. The recommended run path uses the Docker profile so the same workload can be reproduced locally.

Install

Install only the packages required by your stack.

OBJX is split by responsibility so runtime, drivers, tooling, and framework adapters can be composed explicitly.

SQLite happy path

Modeling

One model definition across type inference, hydration, and graph operations.

Column builders, naming strategy, codecs, defaults, and relation metadata live in the same core model surface.

Model definition

Keep logical camelCase keys while mapping to physical database names, and still get runtime defaults, typed inserts, and graph-aware relations.

Typed model
import { col, defineModel, hasMany } from '@qbobjx/core';
import { createSnakeCaseNamingPlugin } from '@qbobjx/plugins';

export const Project = defineModel({
  table: 'projects',
  columns: {
    id: col.bigInt().primary().default(() => generateSnowflakeId()),
    tenantId: col.text().generated(),
    budget: col.numeric(),
    profile: col.jsonb().nullable(),
    status: col.enum(['draft', 'active', 'done']).default('draft'),
    createdAt: col.timestamp(),
  },
  relations: (project) => ({
    tasks: hasMany(() => Task, {
      from: project.columns.id,
      to: Task.columns.projectId,
    }),
  }),
  plugins: [createSnakeCaseNamingPlugin()],
});

Advanced column surface

  • bigint, numeric, float, double
  • date, time, timestamp, jsonb
  • enum([...]) and Postgres arrays
  • custom column codecs for write serialization and hydration

SQL expressiveness

  • distinct, groupBy, having
  • typed aggregates and scalar subqueries
  • withCte(...) for common table expressions
  • raw SQL escape hatch with sql, ref, identifier

Runtime power

  • insertGraph, upsertGraph, relate, unrelate
  • nested eager loading and relation expressions
  • ambient execution context and nested transactions
  • official drivers for SQLite, Postgres, and MySQL

PostgreSQL RLS

Request context can be projected into database-enforced RLS.

OBJX can bind execution context values into set_config(...) at transaction start, so PostgreSQL policies based on current_setting(...) can participate in the same request flow.

ORM layer createTenantScopePlugin()

Applies SQL-level filtering when you want application-side tenant scoping.

Database layer executionContextSettings

Projects request context into PostgreSQL session state for true policy enforcement.

Recommended posture Use both together

Keep app-level ergonomics and DB-level guarantees without duplicating setup code.

RLS transaction setup
const executionContextManager = createExecutionContextManager();

const session = createPostgresSession({
  pool,
  executionContextManager,
  executionContextSettings: {
    bindings: [
      { setting: 'app.tenant_id', contextKey: 'tenantId', required: true },
      { setting: 'app.actor_id', contextKey: 'actorId' },
      {
        setting: 'request.jwt.claims',
        value: ({ executionContext }) => ({
          sub: executionContext.values.get('actorId'),
        }),
      },
    ],
  },
});

await executionContextManager.run(
  {
    values: {
      tenantId: 'tenant_a',
      actorId: 'user_123',
    },
  },
  () =>
    session.transaction(async (trx) => {
      return trx.execute(Project.query(), { hydrate: true });
    }),
);

NestJS

Official module, typed session access, and request context wiring.

@qbobjx/nestjs provides a dynamic module, typed session host, request context support, and validation mapping for applications that want explicit framework integration.

Module ObjxModule.forRoot(...)

Boot the runtime once and keep the framework wiring explicit and reusable.

Typed access ObjxSessionHost<TSession>

Use one typed session surface instead of repeating custom decorators and ad hoc providers.

Request context Headers to execution context

Tenant and actor values can flow into transactions and Postgres RLS bindings automatically.

NestJS module setup
@Module({
  imports: [
    ObjxModule.forRootAsync({
      global: true,
      useFactory: async () => ({
        session: createPostgresSession({
          pool,
          executionContextManager: createExecutionContextManager(),
          hydrateByDefault: true,
          executionContextSettings: {
            bindings: [
              { setting: 'app.tenant_id', contextKey: 'tenantId', required: true },
              { setting: 'app.actor_id', contextKey: 'actorId' },
            ],
          },
          plugins: [
            createTenantScopePlugin(),
            createSoftDeletePlugin(),
          ],
        }),
        requestContext: { enabled: true },
      }),
    }),
  ],
})
export class AppModule {}

Operational workflow

Tooling and operational paths are part of the repo.

The repository already includes codegen, migrations, seeds, examples, Pages docs, and benchmark suites that can be rerun directly.

Codegen

Introspect SQLite, Postgres, or MySQL and bootstrap models or starter templates.

Migrations

Run typed migration schemas with explicit up/down direction and tracked history.

Seeds

Seed and revert data with versioned seed history per dialect.

Benchmarks

Keep performance visible with reproducible Docker-backed comparisons inside the repo.