Your schema is the database
Write one .forge schema. ForgeDB compiles it into a real
columnar database, a REST API, and typed clients for
TypeScript, Python, Rust, and Go — every type, query, and route
tailored to your schema at compile time. Not a runtime ORM. Nothing reflects
your schema at runtime.
Write the schema. Get the stack.
Every type, query, filter, relation, and route is generated and tailored to your models — then compiled. The database that runs already knows your data by name; nothing reflects a schema at runtime.
// schema.forge — the single source of truth
User {
id: +uuid
name: string @length(1, 100)
email: &string @email
created_at: +timestamp
posts: [Post]
}
Post {
id: +uuid
title: string @length(1, 200)
slug: &string
views: ^u64
published: bool
author: *User
created_at: +timestamp
@projection(card: title, slug, views)
}Typed clients in the languages you already ship
The same schema generates a network client for every language on your stack — dataclasses in Python, structs in Rust and Go, interfaces in TypeScript. Same methods, same shapes, no hand-written HTTP and no drift between them.
import { ForgeDBClient } from "./generated/types";
const db = new ForgeDBClient("http://localhost:3000");
// createPost() is typed to PostCreate; returns the new id
const id = await db.createPost({
title: "Hello, ForgeDB",
slug: "hello-forgedb",
views: 0,
published: true,
author: userId,
});
// listPost() → ListResult<Post> { data, total, limit, offset }
const { data, total } = await db.listPost({
filter: { published: true },
sort: "views",
order: "desc",
limit: 10,
});Prefer to embed the database instead of calling it over HTTP? The same schema also generates in-process native bindings — PyO3 for Python, NAPI-RS for Node and Bun, and a WASM read-replica for the browser. See the generate command →
Your schema is a compile-time input to generation — never a runtime input to a generic engine.
That one decision is why there's no query planner to fight, no ORM to out-clever, and no schema drift to chase down. The generated code already knows your data; the substrate it links — storage, WAL, change feed, auth — knows nothing about it, and never will. Read the concepts →
A real database, batteries generated in
Durability, concurrency, real-time, multi-tenancy — the things you'd bolt on later are generated per schema over a small, published substrate. And every one is honest about exactly where its limits are.
End-to-end type safety
Your schema becomes tailored types in Rust, TypeScript, Python, and Go. Schema drift is impossible — the types are generated at compile time, never reflected at runtime.
Learn moreColumnar storage
Fixed-width and variable-length columns with a tiny on-disk footprint and column-pruned scans generated per model.
Learn moreCrash-safe durable writes
Every write hits a per-model WAL with an fsync barrier before columns, with torn-tail recovery and a single-writer lock.
Learn moreTransactions & MVCC
Atomic generated transactions, optimistic concurrent writers, and a multi-process commit coordinator — three strict tiers.
Learn moreLive queries & change feed
Subscribe over WebSockets to typed inserts, updates, and removals — result-set deltas generated from the same filters as your REST API.
Learn moreMulti-tenancy & auth
Physical dir-per-tenant isolation with a verify-only JWT tenant guard — process-per-tenant, generated code stays tenant-oblivious.
Learn moreBrowser read-replica
Compile the same generated database to WASM and follow a durable replication stream — query a local replica in the browser over IndexedDB or OPFS.
Learn morePoint-in-time reads
Lock-free watermark snapshots with zero version machinery — read the database as of an earlier commit over the same REST surface.
Learn moreBackup & migrations
Lock-free full-snapshot backup/restore, plus a version-guarded migration workflow with an offline data transformer.
Learn moreSmall, fast, and honest
Benchmarked fairly — matched durability across engines. At the fsync-barrier tier ForgeDB ties SQLite and redb; relaxed, it's the fastest of the group.
From schema to server
The whole workflow is three commands. Everything else is generated.
Write a schema
Describe your models, relations, and constraints in a declarative .forge file.
User {
id: +uuid
email: &string @email
posts: [Post]
}Generate
Transpile the schema into a tailored Rust database, a REST API, an OpenAPI spec, and typed clients for every language on your stack.
forgedb generate all --output ./generatedBuild & serve
Compile the generated crate and run the server — a real REST API over columnar storage.
forgedb build && ./target/release/serverStop writing the same data layer
Install the CLI, write one schema, and let ForgeDB generate the database, the API, and the typed clients — so you build features, not plumbing.