Sync engine
Sync engine
Pod ships a native sync engine — not a plugin, bolt-on cache, or third-party
replication layer. Tenant apps read and write through $pod/client; when you deploy on
Norbital cloud, Core hosts and proxies the server-side sync transport.
Live reads
Every read is a live query against a policy-scoped local PGlite replica. Use client.db.<collection>.findMany, findFirst, or count — filters, sorts, pagination, and relations compile to local SQL. When a mutation
lands (yours or someone else's), the engine re-evaluates every live query that depends on the
changed collections and diffs the result into the reactive value.
import { client } from '$pod/client';
const orders = client.db.orders.findMany({
where: { status: { eq: 'open' } },
with: { customer: true },
orderBy: { created_at: 'desc' }
});
// Live — another tab or automation closes an order and this result updates. Keyset pagination uses the same cursor format locally and on the server, so pages stay consistent as the replica warms up.
Optimistic writes
Mutations go through create, update, and delete on client.db. The sync engine applies the change to a local overlay on the same frame so
the UI responds instantly. The server confirms or rejects asynchronously through collection_ops — permissions, hooks, audit, history, approvals, and versioning always
apply. A rejection rolls back the overlay and surfaces the reason.
import { client } from '$pod/client';
await client.db.claims.create({
employee_id: employeeId,
amount: 1500,
description: 'Travel reimbursement'
});
// UI updates same-frame. Server confirms or rejects through collection_ops. The invariant
The read path never waits for data this device has already seen. Every server
answer is folded into the local replica. The second visit to anything is instant — no invalidate, refetch, or revalidate in app code.
Policy-scoped local replica
The client maintains one PGlite database per origin. Catch-up syncs whole collections under
policy — filters, sorts, and pagination are pure local SQL over warm tables. Rows outside policy
scope never reach local storage; the server evicts them with leave events on the
change stream.
When the browser supports it, a SharedWorker owns the replica so multiple tabs share one catch-up and one set of tables. Reload opens PGlite with tables already populated, renders from local data on the first frame, then reconnects the stream at the persisted cursor.
Resident and windowed collections
A collection is resident when its policy-scoped rows fit the residency cap. Everything about a resident collection — filter, sort, page, count, relations, search — is local and instant.
Above the cap it is windowed. The replica holds a working set built from queries the app actually makes; primary-key lookups that hit stay instant even on large collections. Some reads (counts, search, incomplete pages) still go to the server when a window alone would produce a wrong answer rather than a stale one.
pod sync CLI — filesystem compiler sync that generates .norbital/ types and registries before build.Workspace Studio preview sync — checkpoint build that applies DDL and records an immutable release artifact. See Workspace Studio.
Related guides
- Collections — define the models live queries read
- Apps — compose operational UIs on top of live reads
- Policies & Approvals — scope what reaches the local replica