Skip to content

Core concepts

Layeron Database gives application code one logical SQL store while Layeron manages the Cloudflare D1 resources behind it.

A db(...) declaration creates one logical Database product instance:

Terminal window
const database = db({
name: "main",
sql: "create table posts (id text primary key, title text not null);",
})

The name becomes part of the platform identity for this Database instance. See Namespaces for namespace defaults and naming rules.

schema is the typed table declaration for Database:

Terminal window
const database = db({
name: "main",
schema: {
posts: table({
id: text().primaryKey(),
title: text().notNull(),
createdAt: integer().notNull(),
}),
},
})

Schema gives you two things:

  • Generated SQL for the initial migration.
  • TypeScript types for database.table("posts").

Raw SQL remains a first-class surface. Use it for SQL that is clearer or more powerful as direct SQLite/D1 statements:

Terminal window
const rows = await database.sql<Post>(
"select id, title from posts where createdAt > ? order by createdAt desc",
[after],
).all()

Migrations evolve the database. They can come from schema, raw SQL strings, or named migration objects. Layeron tracks applied migrations per environment and applies pending migrations during dev and deploy flows.

Capacity controls how many D1 shards back the logical Database instance:

ModeMeaning
fixedOne D1 shard.
manualA user-selected shard count.
autoA declared automatic expansion policy.

The route-level Database API stays the same across these modes.

A multi-shard database needs a sharding policy so D1 Plus can route statements:

Terminal window
sharding: {
tables: [
{ name: "posts", keyColumn: "authorId" },
],
}

The key column should be stable and naturally present in reads and writes, such as tenant, account, user, workspace, or object IDs.