Database
EdgeBase Database runs on SQLite across two edge backends: single-instance DB blocks default to D1, while dynamic DB blocks run on Durable Objects with embedded SQLite. You get CRUD, queries, full-text search, access rules, schema validation, and automatic migrations without managing separate database infrastructure.
Key Features
CRUD + Batch
Insert, update, delete, upsert — single or batch
Queries
Filter (where), sort (orderBy), paginate (offset or cursor-based), OR conditions
Schema Validation
Declarative schema with type checking, required fields, min/max constraints
Full-Text Search
FTS5 with trigram tokenizer — works with CJK and all languages
Realtime
onSnapshot subscriptions with server-side filtering and automatic delta sync
Access Rules
Deny-by-default, per-operation rules with auth and resource context
DB Triggers
Run server-side code automatically on insert, update, or delete
Migrations
Lazy migration engine — automatic for additions, explicit SQL for destructive changes
Multi-Tenancy
DB blocks (app, user:{id}, workspace:{id}) for physical data isolation
DB Blocks
EdgeBase uses DB blocks to route SQLite storage by access pattern:
client.db('app') // One single-instance DB block (D1 by default)
client.db('user', userId) // Per-user isolated DB block
client.db('workspace', 'ws-456') // Per-workspace isolated DB block
Plain block names are not special. app, catalog, public, or any other descriptive name can be a single-instance DB block. Older docs often used shared, but it was only an example name, not a separate product concept.
Each DB block is its own SQLite database. Tables inside the same block can JOIN each other because they share one backing database. Single-instance blocks default to D1 for globally shared data, while dynamic blocks scale out on Durable Objects for per-user, per-workspace, or per-tenant isolation.
Quick Example
// Define schema
app: {
tables: {
posts: {
schema: {
title: { type: 'string', required: true, max: 200 },
content: { type: 'text' },
status: { type: 'string', default: 'draft' },
},
access: {
read() { return true },
insert(auth) { return auth !== null },
update(auth, row) { return auth !== null && auth.id === row.authorId },
delete(auth) { return auth !== null && auth.role === 'admin' },
},
},
},
}
// Client SDK
const post = await client.db('app').table('posts').insert({
title: 'Hello World',
content: 'My first post.',
});
Server-side database operations, raw SQL, and DB block access are available across all Admin SDKs.
Next Steps
CRUD operations, queries, batch, realtime subscriptions
Server-side operations with Service Key (bypasses rules)
Type mapping, auto fields, migrations, destructive change detection
Deny-by-default access control for tables
Server-side code on data changes
Upsert, full-text search