AbsoluteJS

Sync Release Notes

@absolutejs/sync is at 2.9.1. The 1.0 release froze the public API across every subpath; the 1.x line layered on the sandbox, sync packs, Code Mode, cluster cursors, backpressure, tracing, point-in-time replay, and tenant migration; the 2.x line opened with the move to the drizzle-orm 1.0 RC peer line. Sync 2.9.1 requires drizzle-orm >=1.0.0-rc.4 <2. Applications install the current RC exactly and own the single Drizzle runtime; libraries declare that range as a peer. This remains a forward feature until Drizzle 1.0 is stable. Every entry below summarizes the package releases.

#Benchmark trust numbers

The headline numbers are intentionally simple because they map to real trust decisions:

Reconnect correctness
800/800
writes delivered across 100 disconnect iterations in the reconnect bench
Dropped writes
0
dropped writes across all 100 forced disconnects
Sandbox cold start
2ms
median isolated-jsc FFI cold spawn in the shootout bench
Test count
593
tests in the suite as of 1.24.0 — every release below landed with its own tests

The sync suite covers the shipped engine path end to end, including sandbox actions, metrics, bridgeFetch, and MCP registration behavior. The benchmark work is tracked in absolutejs/benchmarks PR #13.

#Release timeline

The full arc from the 1.0 API freeze to the current 2.9.1 release — patch releases fold into the feature they belong to. Highlighted pills mark the launch, the 2.x major, and the current version.

1.0.0
API freeze — sync launches
Public API declared stable across every subpath: reactive push, ORM-derived topics, live queries, the write-behind cache, and the Tier 3 engine with CRDTs, CDC, search, scheduled functions, and devtools.
1.1.0
Reactive fan-out is no longer O(N)
Reactive reruns memoized per change batch — the 1,000-subscriber tail drops from ~1.6 s to ~81 ms (20.3×).
1.2.0
client disconnect()
Force-close the WebSocket without losing state; auto-reconnect resumes via since with a catch-up diff.
1.3.0
Cross-client reactive query cache
N fresh subscribers to the same (collection, params, ctx) run the query body once; overlapping writes invalidate and refresh the entry.
1.4.0
Sandboxed mutation handlers
defineMutation accepts a sandboxedHandler string that runs inside an @absolutejs/isolated-jsc isolate with per-mutation memory and timeout caps.
1.5.0
OCC retry for mutations
Opt-in RetryPolicy re-runs handlers on serialization failures with exponential backoff and fresh actions per attempt.
1.6.0
Outbound CDC streaming
engine.streamChanges() yields historical then live commits; the syncCdc plugin exposes it as a Server-Sent Events route.
1.7.0
Sandbox backend selection
SandboxConfig.backend opts handlers into the FFI backend — ~300 KB cold heap versus ~46 MB on Worker.
1.7.5
Sandbox performance arc lands
Five bench-driven rounds across 1.7.2 → 1.7.5 (with isolated-jsc 0.5 and 0.6) take FFI pure warm dispatch from 4.69 ms to 0.33 ms.
1.7.6
Handler metrics
handlerMetrics fires a per-call record (duration, CPU, heap, success or error) for every sandboxed mutation; sink failures never break user traffic.
1.7.7
actions.now()
Engine-controlled wall clock inside mutation handlers, setting up deterministic replay and optimistic rebase.
1.7.8
bridgeFetch
Allowlisted HTTP from inside the sandbox with host-side credential injection — the secret never enters the JSC heap.
1.7.9
MCP server
@absolutejs/sync/mcp exposes collections, mutations, snapshots, inspection, and mutation runs to MCP-aware clients through five tools.
1.8.0
TanStack DB adapter
@absolutejs/sync/tanstack-db lets TanStack DB own the client collection graph while sync supplies the live transport and server mutations.
1.8.1
isolated-jsc 0.8 runners
sandboxedHandler moves to createIsolatedRunner() with the tenant-script policy and precompiled callables (isolated-jsc 0.8).
1.9.0
Sync packs
engine.registerPack(pack) registers a self-contained bundle of schemas, permissions, collections, mutations, and schedules; conflicting ownsTables claims throw.
1.9.2
Testing subpath
@absolutejs/sync/testing ships createTestEngine, expectRejection, and runAsActor for engine and pack tests.
1.10.0
Code Mode subpath
engineMutationsAsHostTools exposes the mutation surface as host tools for @absolutejs/ai Code Mode scripts.
1.11.0
Atomic mutation batches
engine.runMutations runs N mutations in one transaction with one live diff; transactionalBatchAsHostTool pairs it with Code Mode.
1.12.0
unsafeHost escape hatch
Declared host functions become callable from a sandboxed handler — loud by name, routed through the existing dispatch Reference.
1.13.0
Engine introspection + retention
engine.metrics() for operator scraping, time-based change-log retention via changeLogRetainMs, and per-mutation counters.
1.14.0
Slow-client signaling
connection.stats() plus WS-layer slow-client detection (maxBufferedBytes, onSlow, closeOnSlow).
1.15.0
AbortSignal support
First-class cancellation on subscribe and hydrate — a mid-flight abort stops CPU work nobody will ever read.
1.16.0
Pluggable wire format
FrameSerializer seam on both ends — swap JSON for msgpack or cbor to cut hydrate bandwidth 40–60%.
1.17.0
Cross-instance resume cursor
Clients reconnecting to a different cluster shard resume with a catch-up diff instead of a fresh snapshot.
1.18.0
Client-side cursor plumbing
The 1.17 cursor flows end-to-end through syncClient, syncCollection, and syncStore; legacy numeric since keeps working.
1.19.0
Change-log snapshot / restore
exportChangeLog / importChangeLog keep cursor resumability across a shard reboot.
1.20.0
Mutation backpressure
mutationConcurrency FIFO semaphore plus mutationQueueLimit — clean 429s instead of unbounded queues.
1.20.1
Subscription backpressure
Per-tenant subscriptionLimit rejects before any state allocation; slots release on unsubscribe or abort.
1.21.0
OpenTelemetry tracing
Optional tracerProvider emits sync.runMutation and sync.subscribe spans; a zero-allocation noop when unset.
1.22.0
Point-in-time replay
engine.replayTo({ at, tables }) folds the change log into per-table state at a target timestamp.
1.23.0
Devtools replay surface
A clickable Replay panel plus a GET <path>/replay JSON endpoint wire replayTo into the devtools dashboard.
1.24.0
Tenant migration primitives
engine.fence / exportSnapshot / importSnapshot — three composable verbs to move a tenant between engines.
2.1.0
The 2.x line opens
Breaking peer move: drizzle-orm advances to the 1.0 RC line. engine.metrics().source exposes change-source liveness so CDC-fed health checks can catch a silent feed.
2.2.0
Affects gate
Optional CollectionDefinition.affects() skips re-hydrates for subscriptions a change provably cannot touch — fan-out drops from O(all subscribers) to O(affected).
2.9.1
Current release
Compatibility patch — Drizzle integrations require drizzle-orm 1.0.0-rc.4 or newer on the 1.x line, with the app owning the single runtime. Current release.

#TanStack DB adapter

The @absolutejs/sync/tanstack-db subpath (added in 1.8.0) returns TanStack DB collection options. TanStack DB owns local collection queries and reactivity; Absolute Sync owns WebSocket catch-up, reconnect, server-authoritative mutations, offline mutation replay, and optional local-first read cache.

TS
import { createCollection } from "@tanstack/db";
import { createSyncTanStackCollectionOptions } from "@absolutejs/sync/tanstack-db";

type Order = { id: string; total: number; status: string };

const orders = createCollection(
	createSyncTanStackCollectionOptions<Order>({
		id: "orders",
		url: "ws://localhost:3000/sync/ws",
		collection: "orders",
		getKey: (order) => order.id,
		mutations: {
			insert: "createOrder",
			update: "updateOrder",
			delete: "deleteOrder"
		}
	})
);

@tanstack/db is optional and pinned to >= 0.6.7 <0.7 because the TanStack DB API is still pre-1.0. The adapter accepts string or number keys, matching TanStack DB's current key surface.

#Why it matters

Most sync engines make one of three trade-offs: they require a hosted control plane, they need a sidecar service, or they only solve the client cache while leaving server authority and operational boundaries to the application. Sync is built to run inside your existing Elysia process, next to your database, with server-authoritative mutations as the default.

The release arc strengthens that position. The same engine runs tenant-provided mutation code in an isolated JavaScriptCore sandbox, measures it, brokers HTTP credentials for it, exposes it to MCP clients, and proves reconnect catch-up with a repeatable benchmark. The operator releases (1.13 through 1.24) added metrics, backpressure, tracing, point-in-time replay, and tenant migration on top.

#Start here

  • Read We Heard You for the pain-point map and source links.
  • Read vs Firebase if you are migrating away from Firestore or Realtime Database.
  • Read Sandboxed Mutations for isolated handlers, backend choices, metrics, bridgeFetch, and MCP.