Zero 1.8
Observability and Reliability
Installation
npm install @rocicorp/zero@1.8You can now use zero-cache from GHCR:
docker pull rocicorp/zero:1.8.0
# or
docker pull ghcr.io/rocicorp/zero:1.8.0Overview
Zero 1.8 improves observability, performance, and reliability.
Features
- Request-header forwarding:
zero-cachecan forward selected WebSocket upgrade headers to custom APIs usingZERO_MUTATE_ALLOWED_REQUEST_HEADERSandZERO_QUERY_ALLOWED_REQUEST_HEADERS. (#6144, thanks @tjenkinson!) - GHCR Docker images: Zero images are now published to
ghcr.io/rocicorp/zeroas well as Docker Hub. (#6161) - Mutator result type:
MutatorResultis now exported from@rocicorp/zerofor typing helpers that await.clientor.server. (#6223) - Operational metrics:
zero-cacheadds metrics for API calls and startup, initial sync and replication slots, and Litestream backup and restore. (#6203, #6208, #6191, #6199, #6210) - Stability metrics: New serving-lag, CVR, and WebSocket metrics and replication flow-control metrics help diagnose delayed updates, reconnects, and backpressure. (#6157, #6214, #6207, thanks @tantaman!)
Performance
Zero 1.8 speeds up ordered limit() queries, replication after large Postgres writes, and local ZQL queries.
Ordered limit() Queries
Consider a view showing the top 50 open issues:
zql.issue
.where('workspaceID', workspaceID)
.where('status', 'open')
.orderBy('priority', 'desc')
.orderBy('created', 'asc')
.limit(50)If open issues are sparse, Zero may need to look far down the ordered list to find 50 matches. When an issue enters or leaves the top 50, Zero checks the rows near the cutoff to keep the correct 50 issues in the result.
Zero 1.8 lets SQLite seek directly to that boundary instead of scanning earlier rows again. Boundary fetches are 1.09x faster after 50 rows and up to 300x faster at the end of a 100,000-row index.
Ordered Limit Boundary Fetch
Normalized query-path throughput when refilling an ordered limited view. Higher is better.
Faster Replication After Bulk Writes
A bulk import, backfill, or migration can change tens of thousands of rows in one transaction. Zero records each change during replication, and writing them one at a time could make replication fall behind.
Zero 1.8 writes these changes in batches, making persistence 2.25x to 2.48x faster and helping large transactions reach clients sooner.
Replication Change Persistence
Normalized throughput while recording Postgres changes for replication. Higher is better.
Faster Local Queries
When a query first runs, Zero builds its view from data already synced to the client. In Zero 1.8, there is less per-row work needed to run local scans, filters, and relationship lookups.
For example, when running the query on page load:
zql.issue
.where('closed', false)
.related('owner')
.orderBy('createdAt', 'desc')Views can appear sooner and use less client CPU, with local query fetches running 1.57x to 2.36x faster, depending on the query.
Local Query Fetch
Normalized local query throughput. Higher is better.
Fixes
- Logical replication now reconnects when the inbound Postgres stream goes silent.
- Postgres writes no longer use sockets after disconnection.
- The Drizzle adapter now handles array-mode results from Drizzle 1.0 RC
prepareQuery. (thanks @typedrat!) - z2s now compiles queries using
start, and SQLite fetches handlenullstart-cursor fields. - Queries no longer appear
completewith stale or empty results after reconnect. - React Native reads now work with
op-sqlitev17. - View-syncers no longer fail while the first backup is uploading or retry before a restorable backup exists on cold start.
- Zero Docker images now choose the correct default sync-worker count.
- Change-stream catch-up now respects flow control, preventing unbounded in-memory backlogs.
Breaking Changes
None.