Zero 1.7
Query Correctness and Performance
Installation
npm install @rocicorp/zero@1.7Overview
Zero 1.7 focuses on query correctness, performance, and operational safety. It improves consistency with different encodings across Postgres, the SQLite replica, and the in-memory JS query engine, as well as performance improvements under load.
Features
- Immutable query result updates: Query result updates now preserve references for unchanged subtrees, improving compatibility with React memoization and Solid reactivity without the earlier eager-expansion regression. (#6093)
- Additional Postgres scalar types: Zero now syncs selected text-represented Postgres scalar types, including network/address types,
pg_lsn, and theisnextension family, asstringcolumns. These columns can also participate in Zero primary keys. (#6099) - Replication lag diagnostics: Added a
replication.last_total_laggauge so operators can distinguish actual replication lag from a stalled lag-report stream. (#6042)
Performance
Zero 1.7 is a targeted performance win. It makes several important hot paths faster in real applications: keeping up with busy Postgres databases, running relationship-heavy queries, and analyzing queries.
Postgres Change Processing
Zero 1.7 makes the replication path noticeably faster: change streams process about 1.7x-1.9x faster than 1.6. Initial sync is also modestly faster.
We have seen customer workloads max sustainable replication throughput increase from ~750 writes/second to ~2500.
Postgres Change Processing
Normalized throughput for Postgres replication and storage paths. Higher is better.
Flipped Joins
Flipped joins help relationship and existence queries avoid work that used to scale poorly as result sets grew. In Zero 1.7, direct flipped-join batching is roughly 3x faster, and large merge-shaped ZQL queries improve dramatically, reaching 109x faster at 10,000 rows.
Flipped Join Merge Scaling
Normalized throughput for a merge-shaped flipped-join query. Higher is better.
Direct Flipped Join Batching
Normalized throughput for direct flipped-join batching. Higher is better.
Query Analysis and Logging
Zero 1.7 also removes overhead from analyze-query and the inspector. Query analysis tools that record many vended rows avoid the old O(N²) cost, making Debug.rowVended up to 3,241x faster. Logger context allocation is also 1.32x-1.59x faster, reducing overhead in logging-heavy code paths.
Debug.rowVended Scaling
Normalized throughput for query-analysis/debug runs that record vended rows. Higher is better.
Logger Allocation
Normalized throughput for LogContext construction and withContext allocation. Higher is better.
Fixes
- WebSocket close code
1009could trap a client in a reconnect loop by repeatedly resending the same oversized message. - Inspector/analyze-query could show a query plan different from the actual plan generated by the table source.
- Duplicate bundled copies of runtime peer dependencies could break customer-observable behavior such as
Pool instanceofchecks and React single-instance assumptions. - Singular and plural queries with the same AST could incorrectly share a client view.
- React and Solid queries with nested relationships using
one()vslimit(1)could share a view cache entry and return the wrong nested shape. - Removing a query could trigger an assertion.
LIKE/ILIKEmatching in the JS query engine used multiline regex behavior instead of dotall behavior, causing mismatches for strings containing newlines. (thanks @sravan27!)- Range filters (
<,<=,>,>=) could use ordering that differed from SQLite/Postgres ordering. (thanks @sravan27!) - SQLite replica
LIKE/ILIKEbehavior could diverge from Postgres and the in-memory JS matcher. - SQLite replica
ILIKEdid not match non-ASCII case variants such asMÜLLERandmüller. - Litestream-backed deployments could purge change-log entries based on stale claimed backup progress rather than actual backup state. #6123
- Query hydration and pipeline failures now include the query hash, transformation hash, and custom query name when available.
Breaking Changes
None.