I Shipped...

13 August 2026 (1PR)

safe handling for exhausted global sequences

I made global sequence allocation fail safely when the counter reaches its maximum value. The final value can be used once, but any later allocation now returns a clear error instead of wrapping around and reusing an old sequence number, and every current allocation path uses the same guard.

12 August 2026 (1PR)

typed subscription events with safer decoding

I replaced loosely shaped subscription messages with typed events that the native and TypeScript layers can agree on. The subscription manager now prepares the exact row layout once, so each update can decode fixed positions instead of guessing from field names, while unknown or redefined layouts fail clearly.

10 August 2026 (2PRs)

safer numeric claim handling in prepared queries

I fixed prepared queries so a number used in an access rule can be compared correctly even when it arrives in a different integer size. Values that cannot be converted safely keep their original type, which makes the permission check fail closed instead of silently matching the wrong value.

correct routing for prepared policy claims

I fixed prepared permission queries that combine rules with and without a claim. Each active binding now gets the right route information, so the claimless branch no longer disappears or produces results for the wrong binding.

9 August 2026 (5PRs)

updates for the new batch transaction API

I updated Jazz's integration tests and simulation benchmark to use the new transaction API. The tests now pass the correct opening batch identifier and check that a committed batch exists before waiting for the change to become safely stored at the edge.

a faster recovery scan for sequenced transactions

I changed startup recovery to scan only transactions that have a real sequence number. Pending or rejected local transactions are handled by their own replay paths, so recovery no longer spends time scanning unrelated history.

coverage for reconnects after authorization changes

I added a set of reconnect tests that cover membership and permission changes while someone is disconnected. They check that the client receives exactly the rows that were added, changed, or removed, so future changes cannot accidentally reload everything.

a browser benchmark for loading related rows

I added a browser benchmark that measures how long it takes to load a large set of related records. It uses a repeatable project-board dataset and records the row counts and the time needed to turn the returned data into usable objects, giving us public coverage for this path without changing production behaviour.

benchmarks that show where open recovery time goes

I added a testing-only benchmark that measures the main stages of opening Jazz and recovering its saved data. The measurements now follow the current storage layout, including the final step that restores aliases, so future performance work can target real costs.

7 August 2026 (1PR)

SQL-style aggregate results

I made Jazz's SUM, AVG, MIN, and MAX behave like SQL when there are no rows or only null values, while keeping grouped queries and COUNT working as before. I also added support for signed 64-bit numbers and carried the resulting types through the public subscription API.

6 August 2026 (6PRs)

starter compatibility with Better Auth 1.6.24

I updated the starter projects to use the tested Better Auth 1.6.24 release. I replaced an outdated token-request helper with the typed request supported by that release, keeping the starter authentication flows and compatibility checks aligned.

reliable reconnects after permission changes

I fixed reconnects after a user's permissions changed while they were offline. The server now uses a complete membership response when a fast data-progress marker could miss an old-but-newly-visible row or a revoked row, while keeping the fast path for ordinary updates.

deterministic cleanup for local query outputs

I fixed local one-shot reads and streams retaining internal listeners after they had finished or been dropped. They now clean themselves up immediately, including error paths, while shared streams stay alive until their last owner leaves; regression tests cover these cases.

correct relation data across the browser boundary

I fixed browser-worker transport dropping the hidden column-name information needed to decode relation results. Without it, a relation could be matched with the wrong scalar value; the information is now preserved across the boundary, with regression coverage for nested relations.

a repeatable benchmark for scaling routed subscriptions

I added a repeatable benchmark that measures how a large number of routes affects attaching subscriptions, processing writes, retained data, and memory. It covers 1 to 1,000 routes and gives the next optimisation work a trustworthy baseline without changing runtime behaviour.

a benchmark comparing maintained and rebuilt views

I added a benchmark comparing a saved query result that is already kept up to date with one rebuilt from storage. The maintained result stayed at one read and about 494 encoded bytes, while rebuilding grew from 401 to 40,001 reads as the source grew from 100 to 10,000 rows, while producing the same result.

4 August 2026 (4PRs)

phase-level receipts for the R3 first-read benchmark

I added optional timing receipts to our benchmark for reopening a saved database and running its first query. They split the wait into recognisable steps: preparing the query, running it, turning the returned data into rows, and finishing the result. This shows where an optimisation actually helps, while normal reads do not pay the profiling cost.

lower-allocation native UUID formatting

The native code turns binary IDs into UUID strings while it loads data. It was creating several temporary arrays and strings for every ID, so I replaced that with a small reusable table and direct string building, reducing garbage without changing the UUIDs consumers receive.

a faster path for full-snapshot relation joins

When a relationship query starts with two complete sets of data, the old code treated them as if each side had changed separately. That made it do the join twice and then throw away the duplicate work, so I added a special path that builds the answer once; ordinary incremental updates still use the old behaviour.

cached relation target schemas during hydration

When loading a large set of related records, the code kept looking up and copying the same table description for each record. I cache that description for the duration of the load, so the query does less repeated work while returning exactly the same records.