How It Works
Real-Time Subscriptions
Section titled “Real-Time Subscriptions”When a client subscribes to a query, the server:
- Executes the query function against SQLite
- Tracks which tables and documents were read
- Records the filter expression used (if any)
- Sends the result to the client
- On every mutation, checks if the write overlaps with any subscription’s read set or query filters
- If overlapping, re-executes the query and pushes the new result if it changed
This is query-level invalidation — posting a message to #random won’t trigger re-execution of a subscription watching #general.
Full-text search queries use conservative invalidation: any write to the table triggers re-execution, since FTS relevance ranking makes fine-grained overlap detection impractical.
Optimistic Concurrency Control
Section titled “Optimistic Concurrency Control”Mutations use OCC with timestamp-based conflict detection:
- Begin transaction at current timestamp
- Execute mutation, tracking all reads and writes
- Before committing, check if any read documents were modified since the transaction began
- If conflict detected, return error (client retries automatically)
- If clean, commit writes and increment global timestamp
Type-Safe Codegen
Section titled “Type-Safe Codegen”Running zeroback dev (or zeroback deploy / zeroback codegen) generates three files in zeroback/_generated/:
| File | Purpose |
|---|---|
api.ts | Typed function references (api.messages.list, api.messages.send) |
server.ts | Typed query() and mutation() factories with your DataModel |
dataModel.ts | TypeScript types for all your tables |
It also generates zeroback/_generated/manifest.ts, which scans all user function modules, registers them, and exports functions, schema, httpRouter, and cronJobsDef. The static .zeroback/entry.ts (scaffolded once by zeroback init, user-owned) imports from this manifest and wires everything to @zeroback/server/runtime.
Your editor gets full autocomplete for query args, mutation args, and return types.