Durability Tiers
API reference for read and write durability tiers: the options that control how far data must propagate before an operation confirms.
Jazz data propagates through tiers, from fast local confirmation to broader reach.
| Tier | Where | When to use |
|---|---|---|
"local" | On the device | Default. Instant writes, no network needed. |
"edge" | Nearest sync server | Confirm data has left the device before continuing. |
"global" | Central server | Ensure all clients can see the data, regardless of location. |
For background on how data flows between tiers, see How Sync Works.
Write tiers
insert, update, and delete apply locally with no durability guarantee, and return a write handle. Call .wait({ tier: ... }) on those handles when you need confirmation that the write reached a specific durability tier.
See Writing Data for detailed guidance on which tier to use and code examples.
Read tiers
Read durability controls when the first result of a query or subscription is delivered.
| Option | Values | Default | What it does |
|---|---|---|---|
tier | "local" | "edge" | "global" | "local" (browser/client) / "edge" (backend/server) | How far the first result must come from before the query delivers. |
localUpdates | "immediate" | "deferred" | "immediate" | With "immediate", your own local writes appear in the subscription while still waiting for the tier to confirm the initial snapshot. This only takes effect after the subscription has settled at least once. With "deferred", all delivery is held until the tier confirms. |
propagation | "full" | "local-only" | "full" | With "full", the subscription is sent to upstream servers, which push matching data back. With "local-only", only local storage is queried — no server communication. |
These options apply to:
db.all(query, options?)db.one(query, options?)db.subscribeAll(query, callback, options?)useAll(query, options?)/useAllSuspense(query, options?)(React/Expo)new QuerySubscription(query, options?)(Svelte)useAll(query, options?)(Vue)
const todosAtEdgeDurability = useAll(app.todos, { tier: "edge" });export function subscribeTodosAtEdge(db: Db, onCount: (count: number) => void) {
return db.subscribeAll(app.todos.where({ done: false }), ({ all }) => onCount(all.length), {
tier: "edge",
localUpdates: "immediate",
});
}const todosAtEdgeDurability = new QuerySubscription(app.todos, { tier: 'edge' });export function subscribeTodosAtEdge(db: Db, onCount: (count: number) => void) {
return db.subscribeAll(app.todos.where({ done: false }), ({ all }) => onCount(all.length), {
tier: "edge",
localUpdates: "immediate",
});
}export async function readTodosAtEdgeDurability(db: Db) {
return db.all(app.todos.where({ done: false }), { tier: "edge", localUpdates: "immediate" });
}pub async fn read_todos_at_edge_durability(client: &JazzClient) -> jazz_tools::Result<usize> {
let query = QueryBuilder::new("todos").build();
let rows = client
.query(query, Some(DurabilityTier::EdgeServer))
.await?;
Ok(rows.len())
}For most queries and subscriptions, omitting a tier is the right choice: Jazz delivers results from local storage immediately and streams in remote updates as they arrive. Reserve explicit tiers for cases where eventual consistency is not acceptable.
The read tier gates the first delivery of a subscription only. After the initial snapshot
arrives at the requested tier, subsequent updates are delivered as they reach the local node,
regardless of which tier they've propagated to. For example, a subscription with tier: "global"
guarantees a globally-consistent initial snapshot, but later incremental updates from other
clients may arrive through edge tiers before being globally available even if the durability of
the write is set to 'global'.