Skip to content

db-semantic-plannerThe intent-first query planner

Declare what you want. The planner decides how. Then shows you why.

dbsp
pnpm add @dbsp/core @dbsp/adapter-pgsql

See it in action

dbsp

How it works

1

Declare intent

Write what you need in TypeScript or NQL — tables, filters, relations, aggregations.

orm.select('posts').where(eq('published', true)).include('author')
2

Planner decides

The semantic planner analyzes cardinality, chooses JOIN strategy, extracts CTEs, optimizes.

include-strategy: lateral-join (to-one relation)
3

Inspect everything

Every decision is visible via dump() — SQL, parameters, plan reasoning. Debug before you execute.

SELECT ... FROM "posts" LEFT JOIN LATERAL (...) WHERE $1

Why db-semantic-planner?

vs Prisma

No codegen step. Full SQL observability via dump(). The planner shows you why it chose a strategy, not just what SQL it generated. Native multi-tenant with withSchema().

typescript
// See every decision the planner makes
const dump = orm.select('posts')
  .where(eq('published', true))
  .include('author')
  .dump();

dump.plan.decisions
// → [{ type: 'include-strategy',
//      choice: 'lateral-join',
//      reason: 'to-one relation' }]

vs Drizzle

Automatic include strategy selection — no manual JOINs for relations. The planner picks lateral, subquery, or join based on cardinality. Built-in pgvector and ParadeDB helpers.

typescript
// Relations just work — planner decides strategy
const users = await orm
  .select('users')
  .include('posts.comments.author')
  .dump();

// Nested 3-level include — zero manual JOINs
// Result: users[].posts[].comments[].author

vs Kysely

First-class relation handling with .include(). Schema-level type inference without manual interface definitions. Multi-tenant isolation built-in, not bolted on.

typescript
// Multi-tenant in one line
const tenantOrm = orm.withSchema('acme_corp');

const users = await tenantOrm
  .select('users')
  .where(eq('active', true))
  .dump();
// → SELECT * FROM "acme_corp"."users" WHERE ...

Adapter-agnostic core. PostgreSQL-native today.

The core planner, schema DSL, query builders, and NQL work independently of any database. Write once, swap adapters.

PostgreSQL
v1.0 — Stable
pgvectorParadeDBRLSLATERALCTEsWindow FnDISTINCT ONMulti-tenantRange Types
SQLite
Planned
DuckDB
Planned
MySQL
Planned

Ready to build?

7,700+tests
7packages
v1.0stable
MITlicense

v1.0.1 highlights: Range operators (rangeOverlaps, rangeContains, rangeContainedBy), dump({ queryName, correlationId }) for end-to-end request tracking, fixed relation-mode .join() on compile-only adapters.

Released under the MIT License.