420,000 Lines of Tests: TanStack DB Uses AI as a Test Engineer
TanStack DB 1.0 RC1 is out. It lets you work with backend data as if it were local, and the most interesting part is how it used AI agents plus oracle testing to write 420,000 new lines of tests.
TanStack DB 1.0 RC1 has been released.
Here's the one-sentence explanation: it lets you operate on backend data in the frontend as if it were local data. Records returned by APIs become typed collections, components use live queries to join and filter, and changes take effect immediately before syncing to the server.
This sounds like an old story from the Meteor era. Someone asked the same question under the tweet. Tanner Linsley's reply was: No, you can use Convex and TanStack DB together now. That means you don't need to switch backends or switch sync solutions. You start with your existing REST API and TanStack Query, and add persistence, offline writes, and real-time sync when you need them. The query model stays the same; no rewrite required.
This incremental path is the clearest difference between TanStack DB and other local-first approaches. Most approaches require you to switch databases and sync architecture from the start. TanStack DB's approach is to let you start using it first, then decide how far to go.

What's new in 1.0 RC1
Since 0.6, it has added SSR and deep TanStack Start integration, Neon Realtime and Convex adapters, and Preact as the sixth framework adapter. Performance is better, bundles are smaller, and a large number of bugs have been fixed.
Already running in production: Prisma Studio, Unkey's developer dashboard, and Skylight's React Native family calendar app (with offline support). The core package @tanstack/db gets over one million npm downloads per week.
Where the 420,000 lines of tests came from
This is the most interesting part of 1.0.
In the release blog post, Kyle Mathews mentioned a detail: they wrote 420,000 new lines of tests for 1.0. 211 oracle test files across 15 packages.
What is an oracle? It's an independent reference model. Take a sorting function as an example: a traditional unit test inputs [3,1,2] and verifies the output is [1,2,3]. Property testing generates thousands of inputs to verify the sorting rules. An oracle goes further: use another simple implementation to calculate the correct answer, then compare the results of the real implementation and the reference model.

Maintaining database queries is much more complex than sorting. A single live query has to handle inserts, updates, deletes, batch changes, offline edits, server refreshes, and optimistic update rollbacks. Hand-written test cases simply cannot cover it all.
Kyle's approach was to have AI agents run generated historical sequences against the oracle and automatically find inconsistencies. A single agent session could uncover several new classes of bugs. He even said that the work increasingly feels like stopping agents from fixing too much and chasing imaginary edge cases.
Here's a concrete example. A user reported deleting a row and then reinserting it with the same key in the same event loop; subscribers received the delete but not the insert. A direct read could get the new row, but it wasn't in the subscribers' cache. While fixing this bug, they added a broader oracle: after subscribers apply all change messages, the final row set must match a direct read.
Later, an agent challenged this oracle by deliberately changing the message selection logic and found that both versions passed. Digging further revealed a real bug in production code: after a subscriber deletes a row, a synchronous commit makes the same key visible again, and the DB emits an update instead of an insert. The subscriber doesn't have that row at all. The oracle's simulated subscriber used Map.set to handle both insert and update, swallowing the error. After adding rules that insert requires the key to not exist, and update and delete require the key to exist, 26 of the 378 existing cases failed.
This style of testing is much heavier than traditional unit tests, but what it maintains is design understanding, not a single answer.

Migration notes
If you're using 0.9.2 or earlier, 1.0 RC has quite a few breaking changes. $synced has been replaced by $hasPendingWrites, transaction waiting has changed from isPersisted.promise to when('settled'), Query Collection's mutation handler no longer automatically refetches, React hooks have removed the dependency array, and SSR requires an explicit preloadLiveQuery. The migration guide is quite detailed; I recommend going through it.
发布时间: 2026-10-30 05:37