Edit schema.zanith
model User { id Int @id @default(autoincrement()) email String @unique+ phone String? @unique name String?}Every major ORM today generates code from your schema. Zanith doesn't. Your schema is parsed once at runtime into a graph — queries, types, and validation flow from that graph directly. No generate. No rebuild.
Three adapters ship today — pg, postgres.js, and SQLite. MySQL is on the roadmap for v0.4. The architecture is database-agnostic; the adapter set is what scales.
Models
1,000
In flight
47
Queries today
1,204,910
Runtime graph
schema.zanith
1,000 models · introspected at boot
model User { id Int @id @default(autoincrement()) email String @unique createdAt DateTime @default(now())}Recent compiled queries
02 — The cost
The Day-1 experience is great. Pick an ORM, sketch a few models, run generate, ship. The trouble is what compounds — quietly, predictably, along four axes.
Legend
Curves are illustrative — they encode the *shape* of the cost, not sourced numbers. Specific competitor benchmarks appear once we have published comparisons to cite.
Generated client size
01grows linearly with schema. Each model adds a class, methods, relation accessors, and types.
TypeScript compilation
02grows with the generated client. Above a few hundred models the compiler starts to feel it; above a thousand it crashes for some teams.
Hot-reload latency
03grows with watch-time regeneration. The faster you iterate on the schema, the more the regeneration step blocks you.
Deploy pipeline
04blocks on the generation step. Every deploy waits for a fresh client to be produced, regardless of whether the schema actually changed.
The cost compounds. The deeper you go, the more the schema-grow architecture becomes the application's biggest liability.
ZanithPrismaClient is a drop-in for PrismaClient — same constructor, same methods, your $extendschains intact. The schema is introspected live, so there's nothing to generate.
Know before you swap
Run zanith compat scanbefore you touch a line. It counts every call site and names anything the layer won't translate — file:line, with severity. Whatever it can't do, it refuses loudly. It never guesses.
04 — The engine
Zanith reads the schema at startup, parses it once into a graph in memory, and uses that graph directly. Queries compile to parameterized SQL on the way out. Types come from TypeScript inference over the schema, not from a generated .d.ts file.
Four layers, joined on one runtime substrate. None of them runs at build time.
PARSER
layer 01
reads .zanith files at app start
GRAPH
layer 02
the runtime structure, in memory
COMPILER
layer 03
AST → parameterized SQL on each query
ADAPTER
layer 04
pluggable wire driver
What it looks like in code
A typed call on the model API, compiled to parameterized SQL. Inspectable, predictable, no magic on the wire.
const users = await db.user.findMany({ where: { email: { contains: '@example.com' } }, orderBy: { createdAt: 'desc' }, take: 10,});SELECT id, email, name, created_atFROM usersWHERE email ILIKE $1ORDER BY created_at DESCLIMIT 10;On mobile the two blocks stack vertically; the → between them is the compiler.
The schema-change scenario
Edit schema.zanith
model User { id Int @id @default(autoincrement()) email String @unique+ phone String? @unique name String?}App reparse
New field live
No generate. No regenerated client to commit. No watch process to fight. Twenty-five milliseconds, end-to-end.
Memory · 1000 models
The graph holds models, fields, enums, relations, indexes, and uniqueness constraints — all of it, in memory, for the lifetime of the process. A 500-model generated Prisma client commonly runs to tens of megabytes on disk before it's loaded; the runtime graph is an order of magnitude smaller.
Each cell ≈ 10KB · 340 of 1000 cells filled
The schema change is the deploy.
benchmark file
schema scalescale.test.ts
benchmark file
per-op costexecution.test.ts
benchmark file
integrationpipeline.test.ts
The full breakdown — every figure, with comparison anchors, source files, and honest caveats — lives on the proof page.
Open the proof pageEach one shows you what's behind it before you commit to walking through. No newsletter. No waitlist. No demo call. Real destinations, in the order someone usually wants them.
From the schema DSL to the typed query API, end-to-end. Reference, not narrative.
import { createZanith } from 'zanith';import { PgAdapter } from 'zanith/adapters/pg'; const db = await createZanith({ schema: './schema.zanith', adapter: new PgAdapter({ connectionString }),});The engine is small enough to read in an afternoon. Parser, graph, compiler, adapter — that is everything.
The full benchmark suite, with comparison anchors and honest caveats.
Zanith is at v0.2. The engine is real, the tests pass, the SQL is parameterized. Migrations and Studio shipped this release; the remaining gaps are listed plainly on the roadmap.
end · 08 / 08