From ada4e426e87120023a6edcdd1b519652b7ff1708 Mon Sep 17 00:00:00 2001 From: Kyle Mathews Date: Fri, 16 Oct 2026 13:13:52 -0700 Subject: [PATCH 1/3] blog: draft TanStack DB 1.0 RC1 oracle essay --- ...tack-db-1.0-rc1-going-all-in-on-oracles.md | 147 ++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 src/blog/tanstack-db-1.0-rc1-going-all-in-on-oracles.md diff --git a/src/blog/tanstack-db-1.0-rc1-going-all-in-on-oracles.md b/src/blog/tanstack-db-1.0-rc1-going-all-in-on-oracles.md new file mode 100644 index 000000000..44fb12a99 --- /dev/null +++ b/src/blog/tanstack-db-1.0-rc1-going-all-in-on-oracles.md @@ -0,0 +1,147 @@ +--- +title: 'TanStack DB 1.0 RC1: Going All In on Oracles' +published: 2026-10-16 +draft: true +excerpt: 'TanStack DB 1.0 RC1 is here. How oracles helped me find whole classes of bugs and rethink programming with agents.' +library: db +authors: + - Kyle Mathews +--- + +_Agents make the models practical to write. The models help us find and fix whole classes of bugs._ + +I'm delighted to announce on behalf of the core DB maintainers, myself, Sam Willis, Kevin De Porre, and the entire DB community, that TanStack DB 1.0 RC1 is here! + +After 1.5 years of development and betas and many discussions with users, the API is powerful and stable. We expect to ship 1.0 in a few short weeks. + +Since our [0.6 release](https://tanstack.com/blog/tanstack-db-0.6-app-ready-with-persistence-and-includes), we have shipped [server rendering and deep integration with TanStack Start](https://tanstack.com/db/latest/docs/guides/ssr), worked through a long run of correctness problems, and [made DB much faster for applications with many simultaneous live queries](https://github.com/TanStack/db/pull/1987). + +This post covers what shipped for RC1 and what happened when I tried to fix every known DB bug. Oracles turned that apparently finite task into a search for whole classes of failures, changing how I think about programming and the frameworks, infrastructure, and developer tools agents build on. + +If you haven't used it yet, TanStack DB is a reactive client data framework that makes backend data feel local. Records from your API or sync engine become typed collections. Components query them for joined, filtered live results. Optimistic edits appear immediately and reconcile with the server later. + +Perhaps the biggest difference from earlier client-side databases is that you can adopt TanStack DB incrementally. Historically, getting reactive queries, optimistic mutations, and offline support often meant adopting a new database and sync architecture. With TanStack DB, you can start with your existing REST APIs and [TanStack Query](https://tanstack.com/query/latest) setup, immediately gain fast incremental relational queries, and progressively add [local persistence](https://tanstack.com/db/latest/docs/guides/sqlite-persistence), [durable offline mutations](https://tanstack.com/db/latest/docs/guides/offline-transactions), or real-time sync as your needs evolve. Because the application-facing query model stays the same, you can go from a conventional web application to a fully offline-capable, local-first app without rewriting everything along the way. + +We began building DB in early 2025 at [ElectricSQL](https://electric-sql.com/), which incubated the project for its first year and a half. We [shipped the first beta that July](https://tanstack.com/blog/tanstack-db-0.1-the-embedded-client-database-for-tanstack-query). Since [Neon acquired us in August](https://neon.com/blog/electrifying-neon-building-the-realtime-backend), it has continued to back DB and we released yesterday [Neon Realtime](https://neon.com/docs/realtime/overview) with [TanStack DB support](https://neon.com/docs/realtime/sdks/typescript#tanstack-db). + +Adoption is accelerating, with teams using TanStack DB to build everything from developer tools to consumer mobile apps. Prisma uses DB in [Prisma Studio](https://github.com/prisma/studio), its open-source database editor. Unkey uses it extensively across its [developer dashboard](https://github.com/unkeyed/unkey/tree/main/web/apps/dashboard), and Skylight uses DB and its offline capabilities in its [React Native family calendar app](https://www.youtube.com/watch?v=HSUKoa4JoRw). + +Across its packages, DB now has [almost 3 million weekly NPM downloads](https://tanstack.com/db/latest). Compared to [weekly downloads of React](https://tanstack.com/stats/npm?packageGroups=%5B%7B%22packages%22%3A%5B%7B%22name%22%3A%22%40tanstack%2Fdb%22%7D%5D%7D%2C%7B%22packages%22%3A%5B%7B%22name%22%3A%22react%22%2C%22hidden%22%3Atrue%7D%5D%2C%22color%22%3A%22%2361DAFB%22%2C%22baseline%22%3Atrue%2C%22baselineLabel%22%3A%22React%22%7D%5D&range=1825-days&transform=none&binType=weekly&viewMode=history&chartType=line&barSort=value&bucketOffset=0&playbackIntervalMs=350&playbackLoop=false&playbackPlaying=false&showDataMode=all&normalizeBaseline=true&showBaseline=false&showLegend=false&height=400), downloads of the core DB package have grown roughly tenfold over the past year, to about 0.7% of React's downloads. + +After server rendering landed a few months ago, I thought the remaining work before 1.0 was fairly straightforward: fix every known bug. I'd fire up my agents and set them loose and be done in a few weeks. Before and during that work, though, I tried some new ideas for making the coding environment more productive for agent swarms. The new environment has proved astonishingly effective at finding new bugs and undefined behavior. My short bug-fixing expedition has now stretched to hundreds of PRs and months of intense work hardening DB's core abstractions for 1.0. Since the first PR in this push, the repository has gained roughly 330,000 lines of tests. + +I've worked on open-source libraries for a long time and previously found it hard to find bugs proactively before users provide reproductions. Now essentially every new agent session stumbles on multiple new classes of bugs. After months of fixes, many of these bugs are now so obscure that I suspect no one has encountered them in the wild. Yet they keep coming. Increasingly, my job is to keep agents from fixing _too much_—chasing hypothetical edge cases or adding complexity to solve problems DB never promised to solve. + +## Crafting a playable environment for agents + +The basic problem coding agents present is: when implementation gets cheap, what is left for programmers to do? My answer is _crafting a playable environment for agents_. Programmers shape the _design space_ for swarms of agents: what they can see, which moves they can make, how to judge the results, and what each round passes to the next. + +Over the past few months, I've made the DB repository _playable_ for fresh agent sessions. An agent can find what a part of DB promises, try a small change or challenge that promise, and see the consequences quickly. I can run many short investigations in parallel. What one session discovers becomes the starting point for the next. + +I use one recurring loop: start with a report or design question, ask what general behavior ought to hold, search for counterexamples, then revise the implementation, the rule, or how we verify it. I decide the product promise when it isn't settled. Agents do much of the searching. A bug fix improves DB; a clearer rule or stronger verification improves what later agents can discover. + +Oracles have become the most powerful form of verification in that loop. **Each oracle judges one small part of DB against an independently stated law about what users should observe.** Many use a small reference model to predict what should happen across legal sequences of operations, then compare that prediction with production's public behavior. A unit test can keep one reported failure from returning. An oracle keeps asking whether the rule behind that failure holds across other cases. DB now has **161 oracle test files across 14 packages**, covering [collection change messages](https://github.com/TanStack/db/blob/main/packages/db/tests/change-event-history-oracle.test.ts), [nested live-query includes](https://github.com/TanStack/db/blob/main/packages/db/tests/query/includes-cross-formulation-oracle.property.test.ts), and [cursor pagination](https://github.com/TanStack/db/blob/main/packages/query-db-collection/tests/cursor-pagination.oracle.test.ts), among other behaviors. Sometimes an agent finds that an oracle missed a bug. Strengthening that judge gives later investigations a better instrument. + +I've written and heavily iterated on [oracle-authoring](https://github.com/TanStack/db/blob/main/.agents/skills/oracle-authoring/SKILL.md) and [oracle-review](https://github.com/TanStack/db/blob/main/.agents/skills/oracle-review/SKILL.md) SKILLs, plus a rigorous [14-part rubric](https://github.com/TanStack/db/blob/main/docs/contributing/oracle-rubric.md) that agents use to evaluate and improve their oracles. + +## The bug list kept growing + +No software survives contact with reality. Software becomes battle-tested when many people use it in different ways and maintainers fix what those uses reveal. That maturation normally takes years. + +We made things harder for ourselves with DB's ambitious and radically simple APIs. As our [0.5 post](https://tanstack.com/blog/tanstack-db-0.5-query-driven-sync) put it: “You describe what data you need. DB handles the fetching, caching, and updating.” A single query shapes what DB asks the backend to load across thousands of potential loading scenarios. Our promise that client queries drive data loading and sync has to hold across on-demand queries, pagination, [persistence and offline use](https://tanstack.com/blog/tanstack-db-0.6-app-ready-with-persistence-and-includes), optimistic edits, retries, and reconnection. Consider an issue board showing the ten highest-priority open issues. Complete one, and the replacement may be the eleventh issue, which the client has never loaded. Add pages and offline restarts, and the possible interactions multiply. Some failures are ordinary bugs. Others reveal undefined behavior or push data-loading complexity back into application code. + +When I started tackling our seemingly finite bug list, I surveyed open issues and PRs, grouped related reports, and asked agents what work would solve each entire cluster. One result was the [framework-adapter RFC](https://github.com/TanStack/db/issues/1623) and a [conformance suite](https://github.com/TanStack/db/pull/1636) to make the same public behavior hold across framework adapters. An agent working through another cluster suggested oracle tests. They spread through the RFC work and across DB because each investigation exposed nearby questions the original report hadn't asked. I've merged 350 bug-fixing PRs since starting this work. + +One sequence of fixes makes this loop concrete. A user report led to an oracle, which agents then tried to break. Each blind spot led to a stronger oracle that exposed bugs the previous version couldn't see. The implementation improved, but so did the instrument for investigating it. + +A user [reported a bug](https://github.com/TanStack/db/issues/1901) with collection change messages. They deleted a row and reinserted a replacement with the same key in one turn. A direct read returned the replacement, but a subscriber replaying the messages could end with no row at all. An application maintaining a cache from those messages could silently lose data. + +[PR #1902](https://github.com/TanStack/db/pull/1902) fixed the immediate failure and added an oracle for the broader promise: **a subscriber applying every change message should end up with the same rows as a direct read.** Its reference model is a plain map of keyed rows. It generates legal sequences of inserts, updates, and deletes, runs them both one at a time and batched together, and compares three results: what the map predicts, what DB returns from a direct read, and what a subscriber reconstructs from DB's messages. That checks the reported delete-and-reinsert sequence alongside nearby sequences involving other starting rows, keys, and operation orders. A future change has to preserve the agreement across all of them. + +Then an agent tried removing branches from the collection code to see which ones the tests actually needed. One removal passed the oracle and produced a better change message than the original branch. The oracle had a blind spot: its simulated subscriber used the same map operation for an **insert** and an **update**. It could reconstruct the right final rows even when DB sent an update for a row the subscriber had already deleted. A real subscriber that applies updates only to existing rows would reject it or lose the row. + +I strengthened the rule the subscriber checks as it replays each message: **insert requires an absent key; update and delete require a present key.** The old code then failed 26 of 378 histories already reaching that path. [PR #1995](https://github.com/TanStack/db/pull/1995) made DB send an insert when the key became visible again. The same generated histories now check both the final rows _and_ whether every message was valid at the moment a subscriber received it. The original oracle could catch a missing row; the stronger one can catch a broken message even when the final rows happen to match. + +A review exposed another gap. While reviewing [PR #2004](https://github.com/TanStack/db/pull/2004), CodeRabbit found that replacing the server's source rows during an optimistic edit could send **two inserts for the same key**. The existing subscriber setup filtered out the second insert before the oracle saw it. For [PR #2005](https://github.com/TanStack/db/pull/2005), an agent added a subscriber seeded with the current visible rows that received the raw change messages. After every batch, it checks whether each message is valid for the rows that subscriber actually holds, then compares the subscriber's reconstructed rows with the independent model. The old code failed seven cases. The fix published each key once, and the stronger oracle went on to find another invalid insert when a pending delete crossed an optimistic insert. The new observation point made an entire path of previously hidden failures visible. + +The original report was fixed in #1902. The stronger oracle still found invalid updates and duplicate inserts. Fixing the reported sequence became the start of an investigation into the broader contract. + +Other investigations require me to decide the promise before an oracle can enforce it. During a code simplification audit, an agent found a case where an ordered query's row changed value A → B → A while notifications were held, but also moved behind another row. DB sent no callback when it released the result. A subscribed component could keep showing the old order. I chose the last result subscribers **actually saw** as the comparison point: the private value excursion needs no update, but the public move needs a notification. The oracle for [PR #1933](https://github.com/TanStack/db/pull/1933) runs that held sequence through a real ordered query, checks that nothing is published during the hold, and compares the final rows and callbacks with a small model that sorts the source rows. Neighboring cases distinguish a pure move from a lasting value change. The old implementation missed the final callback; the repaired one passes those checks. + +This is how I pursue a whole class of bugs. I turn the report into a law, generate related histories, and check the public behavior at the point where a user or subscriber would notice the difference. I also test the instrument against the old implementation or a plausible wrong change. When another path reveals a blind spot, I expand what the oracle drives or observes. That stronger instrument stays in the repository for the next agent. + +## Look for cranes + +I've been reading Daniel Dennett's [_Darwin's Dangerous Idea_](https://www.simonandschuster.com/books/Darwins-Dangerous-Idea/Daniel-C-Dennett/9780684824710). Darwin's startling claim, in Dennett's account, was that natural selection, with no foresight, could produce eyes, brains, and other astonishingly intricate adaptations. Many people doubted that a blind process could do this and looked for an outside intelligence to supply the design. Dennett calls that explanatory move a **skyhook**: it lifts the finished complexity into place from above, like the _deus ex machina_ of Greek theater, where stage machinery lowers a god to resolve a plot. To explain how complexity actually develops, we need mechanisms that work within the process. + +Dennett calls these evolutionary mechanisms **cranes**—construction cranes. Both skyhooks and cranes lift; the difference is that a crane stands on the ground and works from what is already there. In evolution, a crane makes more possibilities reachable for the next round of variation and selection. Sexual reproduction, for example, shuffles inherited variants into new combinations, opening paths that mutation in a single lineage would reach much more slowly. A new crane often builds on older cranes. The path to complexity runs through accumulating mechanisms to speedily explore and test the design space. + +The skyhook story in agentic programming is that a sufficiently intelligent model, given a repository, will infer every unstated rule and deliver the right system in one leap. One-shot coding makes that easy to believe for familiar tasks, but those successes stand on compilers, types, libraries, conventions, examples, tests, and a vast history of solved problems in the model's training. Every substantial software project runs into questions that history hasn't settled. Features interact in unexpected ways; new uses reveal missing guarantees; performance work opens up alternative implementations. There is no finished answer for an agent to retrieve. The work is to search the design space, decide what should hold, and test candidate answers. Agents need cranes that make that search productive and preserve what each investigation learns. + +For agents working on DB itself, an oracle is a crane because it turns a reported failure into a repeatable search over a law. [Fast-check](https://fast-check.dev/) generates legal sequences of operations and shrinks a failure into a short counterexample. An agent can run proposed fixes and simpler implementations through the same instrument and see where their behavior diverges. The oracle makes many neighboring cases cheap to explore and bad candidates easy to reject. + +I've set up the repository so a fresh agent can use these instruments without reconstructing months of design decisions. [Project guidelines](https://github.com/TanStack/db/blob/main/AGENTS.md) point it to the glossary, architecture documents, and [coverage map](https://github.com/TanStack/db/blob/main/docs/contributing/oracle-coverage.md), which identifies the oracle responsible for each behavior and its limits. The oracle files put the law beside the small model, generated histories, production path, and comparison, so an agent can read the promise and run an experiment in the same place. The [authoring](https://github.com/TanStack/db/blob/main/.agents/skills/oracle-authoring/SKILL.md) and [review](https://github.com/TanStack/db/blob/main/.agents/skills/oracle-review/SKILL.md) guides teach agents to strengthen that experiment; hostile reviewers follow the same paths to find plausible wrong implementations. A new session starts with a map of the system, runnable experiments, and ways to challenge the experiments themselves. + +Framework conformance tests and benchmarks add feedback for shared behavior and speed. I've also used [TLA+](https://lamport.org/tla/tla.html) to explore the possible sequences of a proposed [query-scoped subscription design](https://github.com/TanStack/db/issues/1935). + +I shape the _fitness landscape_ generally by editing the [AGENTS.md](https://github.com/TanStack/db/blob/main/AGENTS.md). For example I say "all PRs must be net negative for production code". This pushes agents hard to avoid bloated and duplicative implementations. + +That extensive machinery I've developed matters because DB's API opened a huge design space. On-demand queries, pagination, persistence, optimistic writes, and synchronization meet in combinations we never enumerated when designing it. Together, these instruments help us build a richer theory of how clients should load, update, reconcile, and present data. + +Paradoxically, the bug list keeps growing because our ability to find bugs keeps improving. Three months and many billions of tokens have produced more than a pile of fixes: agents now investigate DB with instruments that get sharper as they use them. That change in their working environment has mattered far more than any model upgrade I've seen. + +## Superhistory + +An afternoon can compress what used to be weeks of software history. Venkatesh Rao calls this agent-mediated compression of experience [“artificial time”](https://contraptions.venkateshrao.com/p/superhistory-not-superintelligence). This release push feels like a software-development version of his “superhistory.” I spend much of the day in what feels like a succession of intense design meetings, with fresh evidence arriving 100x faster than I could have gathered it myself. + +Building software starts as an act of invention, but much of its maturation is discovery. DB's API created a world with rules whose consequences we didn't fully know. As users try it and agents probe its combinations, unexpected interactions reveal ambiguities, missing guarantees, and layers of architecture we hadn't anticipated. Some consequences follow from existing promises; others call for new rules. + +That's what superhistory feels like from inside: questions that normally accumulate across years are arriving in months. Implementation work clears quickly, leaving me in a steady stream of design decisions. I spend much more of my day deciding what DB should guarantee and whether a fix simplifies the system or adds unnecessary machinery. Programming has become more intellectually demanding for me even as writing the code has become cheaper. + +Artificial time changes the economics of rigor. An oracle needs a model, generated histories, a production driver, and continuing review as the system changes. Since this push began, DB has gained roughly 330,000 lines of tests—probably more code than I wrote in my entire life before AI. Agents make that work practical. + +## The world DB creates for your agents + +Good programming abstractions create smaller, more consistent worlds for the code above them. A filesystem gives programs files and paths instead of disk sectors. TCP gives them an ordered stream even when the network drops or reorders packets. A programming language gives them functions and types instead of registers and jump instructions. Each settles a mass of lower-level questions so the next layer can make more ambitious moves. + +DB creates a simpler world of client data for application developers and their agents. An agent building an application can work with typed collections backed by TanStack Query over an existing API, a sync engine, or local persistence. It can join issues with projects, show one team's open work, and edit optimistically without building a separate endpoint and cache path for every screen. DB keeps the live results current while handling on-demand fetching, pagination, and reconciliation with the server. + +For that world to exist, DB must deliver on its guarantees. A joined, filtered view stays current as its underlying records change. An optimistic edit appears immediately, then remains when persistence succeeds or rolls back when it fails. With on-demand sync, the query can shape backend requests so a screen loads only the rows it needs. Those promises still have to hold when pagination, offline persistence, and server updates interact—and at the speed a demanding application needs. The last three months of work have been about making this simplified world reliable enough to build on. + +When you start a new application, you can experiment more freely by building on DB's mature data mechanics. You and your agents can focus on behaviors you want to create instead of rebuilding query, cache, and sync behavior for each screen. + +The oracles I've described live in DB's repository. They help me and other contributors strengthen DB; applications benefit from the guarantees they protect. DB's guarantees are an example of what frameworks, infrastructure, and developer tools offer: a detailed theory of how some part of software should work. Their APIs and runtime behavior already shape applications. Coding agents open another route for that knowledge: it can guide the code an agent writes. [SKILLs](https://agentskills.io/home) are a first step, explaining which abstractions to use, what the system guarantees, and where the application has a decision to make. + +I'm exploring how to expose those guarantees directly to agents building applications, beyond written guidance. A framework could provide executable rules, diagnostics, and conformance tests that reach into application code. An agent building a custom sync adapter, for instance, could run it against DB's change-message rules and get a short failing history if it sends an update for a key the subscriber has never seen. + +These are cranes for userland: mechanisms that work inside the application-building process, helping agents explore and construct the next layer on top of a framework. The next generation of frameworks, infrastructure, and developer tools will create rich, lawful, playable worlds for applications and equip coding agents to build within them. + +Here's one idea we're exploring for where to take TanStack DB next: write ordinary server functions to query and mutate Postgres, and DB compiles them into the collections and actions your client uses. + +```tsx +// Server: define a query +const todos = query({ + async handler(req, res) { + return res.json(await db.select().from(todo)) + }, +}) + +// Server: define a mutation +const addTodo = mutation({ + async handler(req, res) { + return res.json(await db.insert(todo).values(req.body).returning()) + }, +}) + +// Client: use the generated collection and action +const { data } = useLiveQuery(todos) +addTodo({ id: crypto.randomUUID(), text: 'Hello world' }) +``` + +_Simplified sketch of an experimental API._ + +DB also generates the data-loading and mutation wiring. When a mutation runs, the client tells the server which query collections are live. The server determines which need updating and returns fresh results with the mutation response. + +Making this work broadly means understanding enough of Postgres's vast language to preserve query meaning, determine which reads a write affects, and reconcile client state correctly. A few years ago, I wouldn't have considered attempting the larger project. The last three months have changed the economics: agents can explore that space, find where the design breaks, and carry stronger instruments into the next investigation. That makes an extraordinarily demanding abstraction tractable enough to pursue. + +I began this push with a finite bug list. It became a continuing process of deciding what DB should promise, finding consequences of those decisions, and giving the next agent stronger equipment for the search. TanStack DB 1.0 RC1 is the result so far. [Try it](https://tanstack.com/db/latest/docs/quick-start) in a demanding application and tell us [what breaks](https://github.com/TanStack/db/issues) or [what DB makes needlessly hard to build](https://github.com/TanStack/db/discussions). Those reports are how the next layer of design begins. From bfab34aea220973d50d9c9c70a66b3e6211d4e80 Mon Sep 17 00:00:00 2001 From: Kyle Mathews Date: Thu, 22 Oct 2026 15:24:06 -0600 Subject: [PATCH 2/3] docs: sync RC1 oracle essay with latest revisions --- ...tack-db-1.0-rc1-going-all-in-on-oracles.md | 64 ++++++++++++------- 1 file changed, 40 insertions(+), 24 deletions(-) diff --git a/src/blog/tanstack-db-1.0-rc1-going-all-in-on-oracles.md b/src/blog/tanstack-db-1.0-rc1-going-all-in-on-oracles.md index 44fb12a99..35b9dde02 100644 --- a/src/blog/tanstack-db-1.0-rc1-going-all-in-on-oracles.md +++ b/src/blog/tanstack-db-1.0-rc1-going-all-in-on-oracles.md @@ -14,15 +14,15 @@ I'm delighted to announce on behalf of the core DB maintainers, myself, Sam Will After 1.5 years of development and betas and many discussions with users, the API is powerful and stable. We expect to ship 1.0 in a few short weeks. -Since our [0.6 release](https://tanstack.com/blog/tanstack-db-0.6-app-ready-with-persistence-and-includes), we have shipped [server rendering and deep integration with TanStack Start](https://tanstack.com/db/latest/docs/guides/ssr), worked through a long run of correctness problems, and [made DB much faster for applications with many simultaneous live queries](https://github.com/TanStack/db/pull/1987). +Since our [0.6 release](https://tanstack.com/blog/tanstack-db-0.6-app-ready-with-persistence-and-includes), we have shipped [server rendering and deep integration with TanStack Start](https://tanstack.com/db/latest/docs/guides/ssr), worked through a long run of correctness problems closing every known bug, added new collection adapters for Neon Realtime and Convex, and [made DB much faster for applications with many simultaneous live queries](https://github.com/TanStack/db/pull/1987). -This post covers what shipped for RC1 and what happened when I tried to fix every known DB bug. Oracles turned that apparently finite task into a search for whole classes of failures, changing how I think about programming and the frameworks, infrastructure, and developer tools agents build on. +Trying to fix every known TanStack DB bug changed how I think about programming. Programming is the iterative work of drawing out design ideas, exploring their consequences, and developing them into a coherent working system. LLMs give us access to an enormous repertoire of ideas and make implementing and investigating them dramatically cheaper. Each investigation can leave the system capable of attempting something more ambitious. This post follows how oracles helped that happen while preparing DB for 1.0—and what it suggests about the future of frameworks, infrastructure, and developer tools. If you haven't used it yet, TanStack DB is a reactive client data framework that makes backend data feel local. Records from your API or sync engine become typed collections. Components query them for joined, filtered live results. Optimistic edits appear immediately and reconcile with the server later. Perhaps the biggest difference from earlier client-side databases is that you can adopt TanStack DB incrementally. Historically, getting reactive queries, optimistic mutations, and offline support often meant adopting a new database and sync architecture. With TanStack DB, you can start with your existing REST APIs and [TanStack Query](https://tanstack.com/query/latest) setup, immediately gain fast incremental relational queries, and progressively add [local persistence](https://tanstack.com/db/latest/docs/guides/sqlite-persistence), [durable offline mutations](https://tanstack.com/db/latest/docs/guides/offline-transactions), or real-time sync as your needs evolve. Because the application-facing query model stays the same, you can go from a conventional web application to a fully offline-capable, local-first app without rewriting everything along the way. -We began building DB in early 2025 at [ElectricSQL](https://electric-sql.com/), which incubated the project for its first year and a half. We [shipped the first beta that July](https://tanstack.com/blog/tanstack-db-0.1-the-embedded-client-database-for-tanstack-query). Since [Neon acquired us in August](https://neon.com/blog/electrifying-neon-building-the-realtime-backend), it has continued to back DB and we released yesterday [Neon Realtime](https://neon.com/docs/realtime/overview) with [TanStack DB support](https://neon.com/docs/realtime/sdks/typescript#tanstack-db). +We began building DB in early 2025 at [ElectricSQL](https://electric-sql.com/), which incubated the project for its first year and a half. We [shipped the first beta that July](https://tanstack.com/blog/tanstack-db-0.1-the-embedded-client-database-for-tanstack-query). Since [Neon acquired us in August](https://neon.com/blog/electrifying-neon-building-the-realtime-backend), it has continued to back DB and we released recently [Neon Realtime](https://neon.com/docs/realtime/overview) with [TanStack DB support](https://neon.com/docs/realtime/sdks/typescript#tanstack-db). Adoption is accelerating, with teams using TanStack DB to build everything from developer tools to consumer mobile apps. Prisma uses DB in [Prisma Studio](https://github.com/prisma/studio), its open-source database editor. Unkey uses it extensively across its [developer dashboard](https://github.com/unkeyed/unkey/tree/main/web/apps/dashboard), and Skylight uses DB and its offline capabilities in its [React Native family calendar app](https://www.youtube.com/watch?v=HSUKoa4JoRw). @@ -34,13 +34,11 @@ I've worked on open-source libraries for a long time and previously found it har ## Crafting a playable environment for agents -The basic problem coding agents present is: when implementation gets cheap, what is left for programmers to do? My answer is _crafting a playable environment for agents_. Programmers shape the _design space_ for swarms of agents: what they can see, which moves they can make, how to judge the results, and what each round passes to the next. +I've been reshaping DB's repository so fresh agents can find the relevant design decisions, experiment, and get clear feedback. That's what I mean by a _playable_ environment: agents can explore possibilities and recognize when a proposed design doesn't hold up. -Over the past few months, I've made the DB repository _playable_ for fresh agent sessions. An agent can find what a part of DB promises, try a small change or challenge that promise, and see the consequences quickly. I can run many short investigations in parallel. What one session discovers becomes the starting point for the next. +I use one recurring loop: start with a bug report or design question, work out what should hold across the whole class of cases, and ask agents to search for counterexamples. I make the product decisions; agents do much of the searching. What we learn stays in the repository so the next investigation can start from it. -I use one recurring loop: start with a report or design question, ask what general behavior ought to hold, search for counterexamples, then revise the implementation, the rule, or how we verify it. I decide the product promise when it isn't settled. Agents do much of the searching. A bug fix improves DB; a clearer rule or stronger verification improves what later agents can discover. - -Oracles have become the most powerful form of verification in that loop. **Each oracle judges one small part of DB against an independently stated law about what users should observe.** Many use a small reference model to predict what should happen across legal sequences of operations, then compare that prediction with production's public behavior. A unit test can keep one reported failure from returning. An oracle keeps asking whether the rule behind that failure holds across other cases. DB now has **161 oracle test files across 14 packages**, covering [collection change messages](https://github.com/TanStack/db/blob/main/packages/db/tests/change-event-history-oracle.test.ts), [nested live-query includes](https://github.com/TanStack/db/blob/main/packages/db/tests/query/includes-cross-formulation-oracle.property.test.ts), and [cursor pagination](https://github.com/TanStack/db/blob/main/packages/query-db-collection/tests/cursor-pagination.oracle.test.ts), among other behaviors. Sometimes an agent finds that an oracle missed a bug. Strengthening that judge gives later investigations a better instrument. +Oracles have become the most powerful form of verification in that loop. **Each oracle judges one small part of DB against an independently stated law about what users should observe.** Many use a small reference model to predict what should happen across legal sequences of operations, then compare that prediction with production's public behavior. A unit test can keep one reported failure from returning. An oracle keeps asking whether the rule behind that failure holds across other cases. DB now has **176 oracle test files across 15 packages**, covering [collection change messages](https://github.com/TanStack/db/blob/main/packages/db/tests/change-event-history-oracle.test.ts), [nested live-query includes](https://github.com/TanStack/db/blob/main/packages/db/tests/query/includes-cross-formulation-oracle.property.test.ts), and [cursor pagination](https://github.com/TanStack/db/blob/main/packages/query-db-collection/tests/cursor-pagination.oracle.test.ts), among other behaviors. Sometimes an agent finds that an oracle missed a bug. Strengthening that judge gives later investigations a better instrument. I've written and heavily iterated on [oracle-authoring](https://github.com/TanStack/db/blob/main/.agents/skills/oracle-authoring/SKILL.md) and [oracle-review](https://github.com/TanStack/db/blob/main/.agents/skills/oracle-review/SKILL.md) SKILLs, plus a rigorous [14-part rubric](https://github.com/TanStack/db/blob/main/docs/contributing/oracle-rubric.md) that agents use to evaluate and improve their oracles. @@ -50,9 +48,9 @@ No software survives contact with reality. Software becomes battle-tested when m We made things harder for ourselves with DB's ambitious and radically simple APIs. As our [0.5 post](https://tanstack.com/blog/tanstack-db-0.5-query-driven-sync) put it: “You describe what data you need. DB handles the fetching, caching, and updating.” A single query shapes what DB asks the backend to load across thousands of potential loading scenarios. Our promise that client queries drive data loading and sync has to hold across on-demand queries, pagination, [persistence and offline use](https://tanstack.com/blog/tanstack-db-0.6-app-ready-with-persistence-and-includes), optimistic edits, retries, and reconnection. Consider an issue board showing the ten highest-priority open issues. Complete one, and the replacement may be the eleventh issue, which the client has never loaded. Add pages and offline restarts, and the possible interactions multiply. Some failures are ordinary bugs. Others reveal undefined behavior or push data-loading complexity back into application code. -When I started tackling our seemingly finite bug list, I surveyed open issues and PRs, grouped related reports, and asked agents what work would solve each entire cluster. One result was the [framework-adapter RFC](https://github.com/TanStack/db/issues/1623) and a [conformance suite](https://github.com/TanStack/db/pull/1636) to make the same public behavior hold across framework adapters. An agent working through another cluster suggested oracle tests. They spread through the RFC work and across DB because each investigation exposed nearby questions the original report hadn't asked. I've merged 350 bug-fixing PRs since starting this work. +When I started tackling our seemingly finite bug list, I surveyed open issues and PRs, grouped related reports, and asked agents what work would solve each entire cluster. One result was the [framework-adapter RFC](https://github.com/TanStack/db/issues/1623) and a [conformance suite](https://github.com/TanStack/db/pull/1636) to make the same public behavior hold across framework adapters. An agent working through another cluster suggested oracle tests. They quickly spread as I saw how effective they are. I've merged 350 bug-fixing PRs since starting this work. -One sequence of fixes makes this loop concrete. A user report led to an oracle, which agents then tried to break. Each blind spot led to a stronger oracle that exposed bugs the previous version couldn't see. The implementation improved, but so did the instrument for investigating it. +### How one oracle got stronger A user [reported a bug](https://github.com/TanStack/db/issues/1901) with collection change messages. They deleted a row and reinserted a replacement with the same key in one turn. A direct read returned the replacement, but a subscriber replaying the messages could end with no row at all. An application maintaining a cache from those messages could silently lose data. @@ -64,9 +62,7 @@ I strengthened the rule the subscriber checks as it replays each message: **inse A review exposed another gap. While reviewing [PR #2004](https://github.com/TanStack/db/pull/2004), CodeRabbit found that replacing the server's source rows during an optimistic edit could send **two inserts for the same key**. The existing subscriber setup filtered out the second insert before the oracle saw it. For [PR #2005](https://github.com/TanStack/db/pull/2005), an agent added a subscriber seeded with the current visible rows that received the raw change messages. After every batch, it checks whether each message is valid for the rows that subscriber actually holds, then compares the subscriber's reconstructed rows with the independent model. The old code failed seven cases. The fix published each key once, and the stronger oracle went on to find another invalid insert when a pending delete crossed an optimistic insert. The new observation point made an entire path of previously hidden failures visible. -The original report was fixed in #1902. The stronger oracle still found invalid updates and duplicate inserts. Fixing the reported sequence became the start of an investigation into the broader contract. - -Other investigations require me to decide the promise before an oracle can enforce it. During a code simplification audit, an agent found a case where an ordered query's row changed value A → B → A while notifications were held, but also moved behind another row. DB sent no callback when it released the result. A subscribed component could keep showing the old order. I chose the last result subscribers **actually saw** as the comparison point: the private value excursion needs no update, but the public move needs a notification. The oracle for [PR #1933](https://github.com/TanStack/db/pull/1933) runs that held sequence through a real ordered query, checks that nothing is published during the hold, and compares the final rows and callbacks with a small model that sorts the source rows. Neighboring cases distinguish a pure move from a lasting value change. The old implementation missed the final callback; the repaired one passes those checks. +The original report was fixed in #1902. The stronger oracle still found invalid updates and duplicate inserts. Each round forced me to spell out more of what collection change messages should guarantee, then teach the oracle to enforce it. This is how I pursue a whole class of bugs. I turn the report into a law, generate related histories, and check the public behavior at the point where a user or subscriber would notice the difference. I also test the instrument against the old implementation or a plausible wrong change. When another path reveals a blind spot, I expand what the oracle drives or observes. That stronger instrument stays in the repository for the next agent. @@ -74,15 +70,15 @@ This is how I pursue a whole class of bugs. I turn the report into a law, genera I've been reading Daniel Dennett's [_Darwin's Dangerous Idea_](https://www.simonandschuster.com/books/Darwins-Dangerous-Idea/Daniel-C-Dennett/9780684824710). Darwin's startling claim, in Dennett's account, was that natural selection, with no foresight, could produce eyes, brains, and other astonishingly intricate adaptations. Many people doubted that a blind process could do this and looked for an outside intelligence to supply the design. Dennett calls that explanatory move a **skyhook**: it lifts the finished complexity into place from above, like the _deus ex machina_ of Greek theater, where stage machinery lowers a god to resolve a plot. To explain how complexity actually develops, we need mechanisms that work within the process. -Dennett calls these evolutionary mechanisms **cranes**—construction cranes. Both skyhooks and cranes lift; the difference is that a crane stands on the ground and works from what is already there. In evolution, a crane makes more possibilities reachable for the next round of variation and selection. Sexual reproduction, for example, shuffles inherited variants into new combinations, opening paths that mutation in a single lineage would reach much more slowly. A new crane often builds on older cranes. The path to complexity runs through accumulating mechanisms to speedily explore and test the design space. +Dennett calls these evolutionary mechanisms **cranes**—construction cranes. Both skyhooks and cranes lift; the difference is that a crane works from solid support. It helps you reach upwards to build a new layer. Once that layer is built, it can support new cranes that reach higher and build further layers. In evolution, a crane makes more possibilities reachable for the next round of variation and selection. Sexual reproduction, for example, shuffles inherited variants into new combinations, opening paths that mutation in a single lineage would reach much more slowly. _The path to complexity runs through accumulating mechanisms to speedily explore and test the design space_. The skyhook story in agentic programming is that a sufficiently intelligent model, given a repository, will infer every unstated rule and deliver the right system in one leap. One-shot coding makes that easy to believe for familiar tasks, but those successes stand on compilers, types, libraries, conventions, examples, tests, and a vast history of solved problems in the model's training. Every substantial software project runs into questions that history hasn't settled. Features interact in unexpected ways; new uses reveal missing guarantees; performance work opens up alternative implementations. There is no finished answer for an agent to retrieve. The work is to search the design space, decide what should hold, and test candidate answers. Agents need cranes that make that search productive and preserve what each investigation learns. -For agents working on DB itself, an oracle is a crane because it turns a reported failure into a repeatable search over a law. [Fast-check](https://fast-check.dev/) generates legal sequences of operations and shrinks a failure into a short counterexample. An agent can run proposed fixes and simpler implementations through the same instrument and see where their behavior diverges. The oracle makes many neighboring cases cheap to explore and bad candidates easy to reject. +For agents working on DB itself, an oracle is a crane because it turns a reported failure into a repeatable search over a law. [Fast-check](https://fast-check.dev/) generates legal sequences of operations and shrinks a failure into a short counterexample. An agent can run proposed fixes and simpler implementations through the same instrument and see where their behavior diverges. The oracle makes many neighboring cases cheap to explore and bad candidates easy to reject. A more precise oracle gives me more freedom to try a simpler algorithm or a faster implementation; benchmarks tell me whether a performance experiment actually improved things. Those experiments can expose further gaps in what we've specified or verified. I've set up the repository so a fresh agent can use these instruments without reconstructing months of design decisions. [Project guidelines](https://github.com/TanStack/db/blob/main/AGENTS.md) point it to the glossary, architecture documents, and [coverage map](https://github.com/TanStack/db/blob/main/docs/contributing/oracle-coverage.md), which identifies the oracle responsible for each behavior and its limits. The oracle files put the law beside the small model, generated histories, production path, and comparison, so an agent can read the promise and run an experiment in the same place. The [authoring](https://github.com/TanStack/db/blob/main/.agents/skills/oracle-authoring/SKILL.md) and [review](https://github.com/TanStack/db/blob/main/.agents/skills/oracle-review/SKILL.md) guides teach agents to strengthen that experiment; hostile reviewers follow the same paths to find plausible wrong implementations. A new session starts with a map of the system, runnable experiments, and ways to challenge the experiments themselves. -Framework conformance tests and benchmarks add feedback for shared behavior and speed. I've also used [TLA+](https://lamport.org/tla/tla.html) to explore the possible sequences of a proposed [query-scoped subscription design](https://github.com/TanStack/db/issues/1935). +Framework conformance tests and benchmarks add feedback for shared behavior and speed. I often use [TLA+](https://lamport.org/tla/tla.html) to explore potential changes to complex designs. I shape the _fitness landscape_ generally by editing the [AGENTS.md](https://github.com/TanStack/db/blob/main/AGENTS.md). For example I say "all PRs must be net negative for production code". This pushes agents hard to avoid bloated and duplicative implementations. @@ -92,31 +88,47 @@ Paradoxically, the bug list keeps growing because our ability to find bugs keeps ## Superhistory -An afternoon can compress what used to be weeks of software history. Venkatesh Rao calls this agent-mediated compression of experience [“artificial time”](https://contraptions.venkateshrao.com/p/superhistory-not-superintelligence). This release push feels like a software-development version of his “superhistory.” I spend much of the day in what feels like a succession of intense design meetings, with fresh evidence arriving 100x faster than I could have gathered it myself. +An afternoon with coding agents can compress what used to be weeks of software history. Venkatesh Rao calls this agent-mediated compression of experience [“artificial time”](https://contraptions.venkateshrao.com/p/superhistory-not-superintelligence). I spend much of the day in what feels like a succession of intense design meetings, with fresh evidence arriving 100x faster than I could have gathered it myself. Building software starts as an act of invention, but much of its maturation is discovery. DB's API created a world with rules whose consequences we didn't fully know. As users try it and agents probe its combinations, unexpected interactions reveal ambiguities, missing guarantees, and layers of architecture we hadn't anticipated. Some consequences follow from existing promises; others call for new rules. -That's what superhistory feels like from inside: questions that normally accumulate across years are arriving in months. Implementation work clears quickly, leaving me in a steady stream of design decisions. I spend much more of my day deciding what DB should guarantee and whether a fix simplifies the system or adds unnecessary machinery. Programming has become more intellectually demanding for me even as writing the code has become cheaper. +That's what artificial time feels like from inside: questions that normally accumulate across years are arriving in months. Implementation work clears quickly, leaving me in a steady stream of design decisions. I spend much more of my day deciding what DB should guarantee and whether a fix simplifies the system or adds unnecessary machinery. Programming has become more intellectually demanding for me even as writing the code has become cheaper. + +Artificial time changes the economics of rigor. Oracles add lots of rigor but are demanding to write and very verbose. Since this push began, DB has gained roughly 330,000 lines of tests—probably more code than I wrote in my entire life before AI. Agents make that work practical. + +Expensive engineering doesn't always come with a business model that can fund it. Client-side infrastructure like DB can be useful to huge numbers of applications without offering an obvious way to charge for that value. Bringing the cost of implementation and design discovery down makes a thoroughly engineered framework possible on a much smaller budget. + +## What source code can't tell an agent + +A codebase is an incomplete account of the software we want to build. It records what the implementation does today, but doesn't reliably tell an agent which behaviors are promises, which are accidents, or why I chose one rule over another. More intelligence cannot reconstruct a decision we haven't made or captured. -Artificial time changes the economics of rigor. An oracle needs a model, generated histories, a production driver, and continuing review as the system changes. Since this push began, DB has gained roughly 330,000 lines of tests—probably more code than I wrote in my entire life before AI. Agents make that work practical. +Design develops through many successive adaptations. Each decision has to fit what's already there, and its consequences reveal further questions to work through. Programmers have always drawn on accumulated design knowledge to make those decisions—recognizing parallels, adapting ideas, and discovering where they stop fitting. LLMs give coding agents a super fast search interface into that history. I use them to explore how those ideas apply to DB's particular problems and gradually develop a more complete and coherent design. This has become the bulk of programming for me. + +Design is immensely complicated. Establishing or improving a single oracle can take hours of investigation between me and my agents: figuring out which distinctions matter, what the system should promise, and whether our model actually expresses that promise. A small executable model can embody a great deal of intellectual work. Those 176 oracle files represent a huge accumulated investment in understanding how this framework should behave. + +Each oracle distills a small part of DB's behavior into an explicit model, with the reasoning behind its rules written beside it. Verifying implementations is one powerful use of that account; helping future programmers and agents understand and extend the system is another. + +An agent working on a change will often run afoul of an oracle and get told its design is wrong. It then reads the oracle carefully to understand the design it needs to respect and revises its approach. Hours of earlier design work guide a later agent at the moment it needs that understanding. + +Design that can talk back. ## The world DB creates for your agents Good programming abstractions create smaller, more consistent worlds for the code above them. A filesystem gives programs files and paths instead of disk sectors. TCP gives them an ordered stream even when the network drops or reorders packets. A programming language gives them functions and types instead of registers and jump instructions. Each settles a mass of lower-level questions so the next layer can make more ambitious moves. -DB creates a simpler world of client data for application developers and their agents. An agent building an application can work with typed collections backed by TanStack Query over an existing API, a sync engine, or local persistence. It can join issues with projects, show one team's open work, and edit optimistically without building a separate endpoint and cache path for every screen. DB keeps the live results current while handling on-demand fetching, pagination, and reconciliation with the server. +DB creates a simpler world for client data for application developers and their agents. An agent building an application can work with typed collections backed by TanStack Query over an existing API, a sync engine, or local persistence. It can join issues with projects, show one team's open work, and edit optimistically without building a separate endpoint and cache path for every screen. DB keeps the live results current while handling on-demand fetching, pagination, and reconciliation with the server. For that world to exist, DB must deliver on its guarantees. A joined, filtered view stays current as its underlying records change. An optimistic edit appears immediately, then remains when persistence succeeds or rolls back when it fails. With on-demand sync, the query can shape backend requests so a screen loads only the rows it needs. Those promises still have to hold when pagination, offline persistence, and server updates interact—and at the speed a demanding application needs. The last three months of work have been about making this simplified world reliable enough to build on. When you start a new application, you can experiment more freely by building on DB's mature data mechanics. You and your agents can focus on behaviors you want to create instead of rebuilding query, cache, and sync behavior for each screen. -The oracles I've described live in DB's repository. They help me and other contributors strengthen DB; applications benefit from the guarantees they protect. DB's guarantees are an example of what frameworks, infrastructure, and developer tools offer: a detailed theory of how some part of software should work. Their APIs and runtime behavior already shape applications. Coding agents open another route for that knowledge: it can guide the code an agent writes. [SKILLs](https://agentskills.io/home) are a first step, explaining which abstractions to use, what the system guarantees, and where the application has a decision to make. +Frameworks, infrastructure, and developer tools embody detailed theories of their domains. Their APIs shape applications; that knowledge can also guide the agents writing them. [SKILLs](https://agentskills.io/home) are a first step. The oracles I've described verify DB itself. DB should also provide oracles for custom collections, so developers and their agents can verify that they sync data correctly and get a short failing history when they don't. -I'm exploring how to expose those guarantees directly to agents building applications, beyond written guidance. A framework could provide executable rules, diagnostics, and conformance tests that reach into application code. An agent building a custom sync adapter, for instance, could run it against DB's change-message rules and get a short failing history if it sends an update for a key the subscriber has never seen. +The framework can also supply instruments for application-specific requirements. DB could expose how much data a query loads or how often it refreshes; an application could set the budgets that matter for its users. The framework supplies the instruments, and the application supplies the requirements. Agents then have both explicit expectations and evidence to guide their changes. These are cranes for userland: mechanisms that work inside the application-building process, helping agents explore and construct the next layer on top of a framework. The next generation of frameworks, infrastructure, and developer tools will create rich, lawful, playable worlds for applications and equip coding agents to build within them. -Here's one idea we're exploring for where to take TanStack DB next: write ordinary server functions to query and mutate Postgres, and DB compiles them into the collections and actions your client uses. +Here's another idea we're exploring for where to take TanStack DB next: write ordinary server functions to query and mutate Postgres, and DB compiles them into the collections and actions your client uses. ```tsx // Server: define a query @@ -144,4 +156,8 @@ DB also generates the data-loading and mutation wiring. When a mutation runs, th Making this work broadly means understanding enough of Postgres's vast language to preserve query meaning, determine which reads a write affects, and reconcile client state correctly. A few years ago, I wouldn't have considered attempting the larger project. The last three months have changed the economics: agents can explore that space, find where the design breaks, and carry stronger instruments into the next investigation. That makes an extraordinarily demanding abstraction tractable enough to pursue. -I began this push with a finite bug list. It became a continuing process of deciding what DB should promise, finding consequences of those decisions, and giving the next agent stronger equipment for the search. TanStack DB 1.0 RC1 is the result so far. [Try it](https://tanstack.com/db/latest/docs/quick-start) in a demanding application and tell us [what breaks](https://github.com/TanStack/db/issues) or [what DB makes needlessly hard to build](https://github.com/TanStack/db/discussions). Those reports are how the next layer of design begins. +There's a useful name for what these cranes improve: _evolvability_, a system's capacity to support further useful development. Autonomy asks how much work an agent can do without me. Evolvability asks what new work becomes possible because of what we've learned. An agent arriving tomorrow can attempt something more ambitious using the same LLM because it inherits better cranes. + +My days are full of decisions about what matters, which promises to make, and when an investigation has gone far enough. Each answer can become part of the machinery that makes further development possible. That's what makes me excited about where programming is going: the possibility of much more robust, delightful, and varied software, including ideas that used to cost too much to pursue. + +I began this push with a finite bug list. TanStack DB 1.0 RC1 is the result so far. [Try it](https://tanstack.com/db/latest/docs/quick-start) in a demanding application and tell us [what breaks](https://github.com/TanStack/db/issues) or [what DB makes needlessly hard to build](https://github.com/TanStack/db/discussions). Those reports are how the next layer of design begins. From dbd97d4db4b6f43472e03f4289075540db8b63a6 Mon Sep 17 00:00:00 2001 From: Kyle Mathews Date: Sat, 24 Oct 2026 12:24:30 -0600 Subject: [PATCH 3/3] docs: sync latest TanStack DB RC1 essay --- ...tack-db-1.0-rc1-going-all-in-on-oracles.md | 163 ++++++++++++------ 1 file changed, 109 insertions(+), 54 deletions(-) diff --git a/src/blog/tanstack-db-1.0-rc1-going-all-in-on-oracles.md b/src/blog/tanstack-db-1.0-rc1-going-all-in-on-oracles.md index 35b9dde02..cf8d6872b 100644 --- a/src/blog/tanstack-db-1.0-rc1-going-all-in-on-oracles.md +++ b/src/blog/tanstack-db-1.0-rc1-going-all-in-on-oracles.md @@ -8,21 +8,28 @@ authors: - Kyle Mathews --- -_Agents make the models practical to write. The models help us find and fix whole classes of bugs._ - I'm delighted to announce on behalf of the core DB maintainers, myself, Sam Willis, Kevin De Porre, and the entire DB community, that TanStack DB 1.0 RC1 is here! After 1.5 years of development and betas and many discussions with users, the API is powerful and stable. We expect to ship 1.0 in a few short weeks. Since our [0.6 release](https://tanstack.com/blog/tanstack-db-0.6-app-ready-with-persistence-and-includes), we have shipped [server rendering and deep integration with TanStack Start](https://tanstack.com/db/latest/docs/guides/ssr), worked through a long run of correctness problems closing every known bug, added new collection adapters for Neon Realtime and Convex, and [made DB much faster for applications with many simultaneous live queries](https://github.com/TanStack/db/pull/1987). -Trying to fix every known TanStack DB bug changed how I think about programming. Programming is the iterative work of drawing out design ideas, exploring their consequences, and developing them into a coherent working system. LLMs give us access to an enormous repertoire of ideas and make implementing and investigating them dramatically cheaper. Each investigation can leave the system capable of attempting something more ambitious. This post follows how oracles helped that happen while preparing DB for 1.0—and what it suggests about the future of frameworks, infrastructure, and developer tools. +After a quick introduction to DB and this release, the post has eight sections: + +1. [From unit tests to oracles](#from-unit-tests-to-oracles): what an oracle is and how it helps explore whole categories of bugs. +2. [Crafting a playable environment for agents](#crafting-a-playable-environment-for-agents): making DB's design knowledge available to coding agents. +3. [The bug list kept growing](#the-bug-list-kept-growing): what I did and learned while making DB epically production ready. +4. [A recipe for designing an oracle](#a-recipe-for-designing-an-oracle): how to build one, and how it relates to formal verification. +5. [Look for cranes](#look-for-cranes): why the tools around a coding agent matter so much. +6. [Superhistory](#superhistory): how agents change the pace and economics of programming. +7. [Drawing out the design](#drawing-out-the-design): how agents help develop and refine DB's design. +8. [The world DB creates for your agents](#the-world-db-creates-for-your-agents): what this means for frameworks and application developers. If you haven't used it yet, TanStack DB is a reactive client data framework that makes backend data feel local. Records from your API or sync engine become typed collections. Components query them for joined, filtered live results. Optimistic edits appear immediately and reconcile with the server later. -Perhaps the biggest difference from earlier client-side databases is that you can adopt TanStack DB incrementally. Historically, getting reactive queries, optimistic mutations, and offline support often meant adopting a new database and sync architecture. With TanStack DB, you can start with your existing REST APIs and [TanStack Query](https://tanstack.com/query/latest) setup, immediately gain fast incremental relational queries, and progressively add [local persistence](https://tanstack.com/db/latest/docs/guides/sqlite-persistence), [durable offline mutations](https://tanstack.com/db/latest/docs/guides/offline-transactions), or real-time sync as your needs evolve. Because the application-facing query model stays the same, you can go from a conventional web application to a fully offline-capable, local-first app without rewriting everything along the way. +Perhaps the biggest difference between TanStack DB and from earlier client-side databases is that you can adopt TanStack DB incrementally. Historically, getting reactive queries, optimistic mutations, and offline support often meant adopting a new database and sync architecture. With TanStack DB, you can start with your existing REST APIs and [TanStack Query](https://tanstack.com/query/latest) setup, immediately gain fast incremental relational queries, and progressively add [local persistence](https://tanstack.com/db/latest/docs/guides/sqlite-persistence), [durable offline mutations](https://tanstack.com/db/latest/docs/guides/offline-transactions), or real-time sync as your needs evolve. Because the application-facing query model stays the same, you can go from a conventional web application to a fully offline-capable, local-first app without rewriting everything along the way. -We began building DB in early 2025 at [ElectricSQL](https://electric-sql.com/), which incubated the project for its first year and a half. We [shipped the first beta that July](https://tanstack.com/blog/tanstack-db-0.1-the-embedded-client-database-for-tanstack-query). Since [Neon acquired us in August](https://neon.com/blog/electrifying-neon-building-the-realtime-backend), it has continued to back DB and we released recently [Neon Realtime](https://neon.com/docs/realtime/overview) with [TanStack DB support](https://neon.com/docs/realtime/sdks/typescript#tanstack-db). +We began building DB in early 2025 at [ElectricSQL](https://electric-sql.com/), which incubated the project for its first year and a half. We [shipped the first beta that July](https://tanstack.com/blog/tanstack-db-0.1-the-embedded-client-database-for-tanstack-query). Since [Neon acquired us in August](https://neon.com/blog/electrifying-neon-building-the-realtime-backend), it has continued to back DB and we recently released [Neon Realtime](https://neon.com/docs/realtime/overview) with [TanStack DB support](https://neon.com/docs/realtime/sdks/typescript#tanstack-db). Adoption is accelerating, with teams using TanStack DB to build everything from developer tools to consumer mobile apps. Prisma uses DB in [Prisma Studio](https://github.com/prisma/studio), its open-source database editor. Unkey uses it extensively across its [developer dashboard](https://github.com/unkeyed/unkey/tree/main/web/apps/dashboard), and Skylight uses DB and its offline capabilities in its [React Native family calendar app](https://www.youtube.com/watch?v=HSUKoa4JoRw). @@ -30,105 +37,151 @@ Across its packages, DB now has [almost 3 million weekly NPM downloads](https:// After server rendering landed a few months ago, I thought the remaining work before 1.0 was fairly straightforward: fix every known bug. I'd fire up my agents and set them loose and be done in a few weeks. Before and during that work, though, I tried some new ideas for making the coding environment more productive for agent swarms. The new environment has proved astonishingly effective at finding new bugs and undefined behavior. My short bug-fixing expedition has now stretched to hundreds of PRs and months of intense work hardening DB's core abstractions for 1.0. Since the first PR in this push, the repository has gained roughly 330,000 lines of tests. -I've worked on open-source libraries for a long time and previously found it hard to find bugs proactively before users provide reproductions. Now essentially every new agent session stumbles on multiple new classes of bugs. After months of fixes, many of these bugs are now so obscure that I suspect no one has encountered them in the wild. Yet they keep coming. Increasingly, my job is to keep agents from fixing _too much_—chasing hypothetical edge cases or adding complexity to solve problems DB never promised to solve. +I've worked on open-source libraries for a long time and previously found it hard to find bugs proactively before users provide reproductions. Now essentially every new agent session stumbles on multiple new classes of bugs. Many of which are now so obscure that I suspect no one has encountered them in the wild. Yet they keep coming. Increasingly, my job is to keep agents from fixing _too much_—chasing hypothetical edge cases or adding complexity to solve problems DB never promised to solve. + +## From unit tests to oracles + +Every software test needs something to try and a way to tell whether the result is right. That second part—the answer key—is called an **oracle**. + +In a typical unit test, I write down a specific example and its expected result: start with three open tasks, mark one complete, and check that the list contains the other two. That expected list is the oracle for that test. I supply the answer by hand. + +The model-based oracles I'm using calculate expected answers for many different examples. Suppose a screen shows the ten highest-priority open tasks. DB's production code uses complex machinery to keep that list current efficiently as tasks change. The model trades efficiency for simplicity: take all the tasks, remove the completed ones, sort by priority, and take the first ten. It rebuilds the whole answer from scratch after every change—a few straightforward lines of code can describe what a much more complex implementation should produce. + +Give the model and DB the same changes, then compare their results. The simple model becomes an independent answer key for the optimized production code. + +```mermaid +flowchart TD + A["Same sequence of changes"] --> M["Simple model"] + A --> D["Real DB"] + M --> E["Expected result"] + D --> R["Actual result"] + E --> C["Compare"] + R --> C +``` + +The answer key can come from a small model I write or an existing tool that's already been thoroughly tested. A built-in JavaScript `Map` can track which keyed rows should exist after a sequence of inserts, updates, and deletes. SQLite can tell us what a query should return—I've used it to validate DB's query behavior. In each case, we have an independent way to calculate the expected answer and compare it with production. + +Now agents can automatically try thousands of sequences—adding tasks, changing priorities, completing and reopening them—while the model calculates the answer after each change. A reported bug becomes the starting point for exploring a whole category of failures: different starting data, different changes, different orders. + +**The model gives us an answer key for cases we never wrote out by hand.** ## Crafting a playable environment for agents -I've been reshaping DB's repository so fresh agents can find the relevant design decisions, experiment, and get clear feedback. That's what I mean by a _playable_ environment: agents can explore possibilities and recognize when a proposed design doesn't hold up. +An agent reading DB's implementation can see what it does today. To make good changes, it also needs to understand which behaviors are promises, which are accidents, and why I chose one rule over another. -I use one recurring loop: start with a bug report or design question, work out what should hold across the whole class of cases, and ask agents to search for counterexamples. I make the product decisions; agents do much of the searching. What we learn stays in the repository so the next investigation can start from it. +I've been reshaping DB's repository into a "playable" environment where fresh agents can find those design decisions, experiment, and get clear feedback. Each oracle captures a small part of DB's intended behavior, with the reasoning behind its rules written beside the model. -Oracles have become the most powerful form of verification in that loop. **Each oracle judges one small part of DB against an independently stated law about what users should observe.** Many use a small reference model to predict what should happen across legal sequences of operations, then compare that prediction with production's public behavior. A unit test can keep one reported failure from returning. An oracle keeps asking whether the rule behind that failure holds across other cases. DB now has **176 oracle test files across 15 packages**, covering [collection change messages](https://github.com/TanStack/db/blob/main/packages/db/tests/change-event-history-oracle.test.ts), [nested live-query includes](https://github.com/TanStack/db/blob/main/packages/db/tests/query/includes-cross-formulation-oracle.property.test.ts), and [cursor pagination](https://github.com/TanStack/db/blob/main/packages/query-db-collection/tests/cursor-pagination.oracle.test.ts), among other behaviors. Sometimes an agent finds that an oracle missed a bug. Strengthening that judge gives later investigations a better instrument. +I use one recurring loop to develop that understanding: start with a bug report or design question and work out the rules for the whole class of cases: -I've written and heavily iterated on [oracle-authoring](https://github.com/TanStack/db/blob/main/.agents/skills/oracle-authoring/SKILL.md) and [oracle-review](https://github.com/TanStack/db/blob/main/.agents/skills/oracle-review/SKILL.md) SKILLs, plus a rigorous [14-part rubric](https://github.com/TanStack/db/blob/main/docs/contributing/oracle-rubric.md) that agents use to evaluate and improve their oracles. +- Which actions are allowed, and which should be rejected? +- What should a user see after each action, and when? +- What should happen if actions overlap, fail, or arrive in a different order? + +I encode that reasoning in the oracle's model, turning the design decisions into precise, executable rules the codebase must satisfy. Then agents search for counterexamples and verify their fixes against those rules across generated cases. The goal is to fix the entire class of bugs, with the model continuing to enforce the design as the codebase changes. + +I make the product decisions; agents do much of the searching. + +DB now has **176 oracle test files across 15 packages**, covering [the messages sent when data changes](https://github.com/TanStack/db/blob/main/packages/db/tests/change-event-history-oracle.test.ts), [how queries assemble related records](https://github.com/TanStack/db/blob/main/packages/db/tests/query/includes-cross-formulation-oracle.property.test.ts), and [which rows pagination returns](https://github.com/TanStack/db/blob/main/packages/query-db-collection/tests/cursor-pagination.oracle.test.ts), among other behaviors. The repository's [coverage map](https://github.com/TanStack/db/blob/main/docs/contributing/oracle-coverage.md) helps agents find the relevant oracle. + +An agent working on a change will often run afoul of an oracle and get told its design is wrong. It then reads the oracle carefully to understand the design it needs to respect and revises its approach. Hours of earlier design work guide a later agent at the moment it needs that understanding. + +Design that can talk back. ## The bug list kept growing No software survives contact with reality. Software becomes battle-tested when many people use it in different ways and maintainers fix what those uses reveal. That maturation normally takes years. -We made things harder for ourselves with DB's ambitious and radically simple APIs. As our [0.5 post](https://tanstack.com/blog/tanstack-db-0.5-query-driven-sync) put it: “You describe what data you need. DB handles the fetching, caching, and updating.” A single query shapes what DB asks the backend to load across thousands of potential loading scenarios. Our promise that client queries drive data loading and sync has to hold across on-demand queries, pagination, [persistence and offline use](https://tanstack.com/blog/tanstack-db-0.6-app-ready-with-persistence-and-includes), optimistic edits, retries, and reconnection. Consider an issue board showing the ten highest-priority open issues. Complete one, and the replacement may be the eleventh issue, which the client has never loaded. Add pages and offline restarts, and the possible interactions multiply. Some failures are ordinary bugs. Others reveal undefined behavior or push data-loading complexity back into application code. +For DB, becoming battle-tested means making the promise that backend data feels local hold up under all those different uses. Components query collections for live results, and edits appear immediately. Behind that simple experience, DB coordinates records arriving from the server, changes made on the client, and updates to what's on screen. -When I started tackling our seemingly finite bug list, I surveyed open issues and PRs, grouped related reports, and asked agents what work would solve each entire cluster. One result was the [framework-adapter RFC](https://github.com/TanStack/db/issues/1623) and a [conformance suite](https://github.com/TanStack/db/pull/1636) to make the same public behavior hold across framework adapters. An agent working through another cluster suggested oracle tests. They quickly spread as I saw how effective they are. I've merged 350 bug-fixing PRs since starting this work. +Loading data a page at a time, saving it across restarts, and supporting offline edits make that coordination much harder. An application can restart with an edit still waiting to reach the server. If a screen has loaded only the ten highest-priority open tasks, completing one means fetching the next task from the server. Each feature introduces more interactions that need to work correctly together. The application still uses the same simple API, but making that abstraction reliable becomes an immense testing problem. ### How one oracle got stronger -A user [reported a bug](https://github.com/TanStack/db/issues/1901) with collection change messages. They deleted a row and reinserted a replacement with the same key in one turn. A direct read returned the replacement, but a subscriber replaying the messages could end with no row at all. An application maintaining a cache from those messages could silently lose data. +Collections notify other code—their subscribers—about changes with insert, update, and delete messages. A user [reported a bug](https://github.com/TanStack/db/issues/1901) where they deleted a row and reinserted a replacement with the same key in one turn. A direct read returned the replacement, but a subscriber replaying the messages could end with no row at all. An application maintaining a cache from those messages could lose data. -[PR #1902](https://github.com/TanStack/db/pull/1902) fixed the immediate failure and added an oracle for the broader promise: **a subscriber applying every change message should end up with the same rows as a direct read.** Its reference model is a plain map of keyed rows. It generates legal sequences of inserts, updates, and deletes, runs them both one at a time and batched together, and compares three results: what the map predicts, what DB returns from a direct read, and what a subscriber reconstructs from DB's messages. That checks the reported delete-and-reinsert sequence alongside nearby sequences involving other starting rows, keys, and operation orders. A future change has to preserve the agreement across all of them. +[PR #1902](https://github.com/TanStack/db/pull/1902) fixed the immediate failure and added an oracle for the broader promise: **a subscriber applying every change message should end up with the same rows as a direct read.** A plain map of keyed rows supplied the expected state. Across generated changes, applied individually and in batches, the oracle compared that state with both DB's direct reads and the rows a subscriber reconstructed from its messages. -Then an agent tried removing branches from the collection code to see which ones the tests actually needed. One removal passed the oracle and produced a better change message than the original branch. The oracle had a blind spot: its simulated subscriber used the same map operation for an **insert** and an **update**. It could reconstruct the right final rows even when DB sent an update for a row the subscriber had already deleted. A real subscriber that applies updates only to existing rows would reject it or lose the row. +Later, an agent tried removing branches from the collection code to see which ones the tests actually needed. One removal produced a better change message, yet both the old and new code passed the oracle. Its simulated subscriber treated an **insert** and an **update** as the same map operation. An update could recreate a row the subscriber had already deleted. The final rows looked right, even though a real subscriber that updates only existing rows would reject the message or lose the replacement. -I strengthened the rule the subscriber checks as it replays each message: **insert requires an absent key; update and delete require a present key.** The old code then failed 26 of 378 histories already reaching that path. [PR #1995](https://github.com/TanStack/db/pull/1995) made DB send an insert when the key became visible again. The same generated histories now check both the final rows _and_ whether every message was valid at the moment a subscriber received it. The original oracle could catch a missing row; the stronger one can catch a broken message even when the final rows happen to match. +I strengthened the rule: **insert requires an absent key; update and delete require a present key.** The old code then failed 26 of 378 histories already reaching that path. [PR #1995](https://github.com/TanStack/db/pull/1995) made DB send an insert when the key became visible again. Agreement on final rows was no longer enough; every message had to be valid when received. -A review exposed another gap. While reviewing [PR #2004](https://github.com/TanStack/db/pull/2004), CodeRabbit found that replacing the server's source rows during an optimistic edit could send **two inserts for the same key**. The existing subscriber setup filtered out the second insert before the oracle saw it. For [PR #2005](https://github.com/TanStack/db/pull/2005), an agent added a subscriber seeded with the current visible rows that received the raw change messages. After every batch, it checks whether each message is valid for the rows that subscriber actually holds, then compares the subscriber's reconstructed rows with the independent model. The old code failed seven cases. The fix published each key once, and the stronger oracle went on to find another invalid insert when a pending delete crossed an optimistic insert. The new observation point made an entire path of previously hidden failures visible. +A review exposed another gap. While reviewing [PR #2004](https://github.com/TanStack/db/pull/2004), CodeRabbit found that replacing the server's source rows during an optimistic edit could send **two inserts for the same key**. The oracle already knew that was wrong, but the subscriber used by the test filtered out the second insert before the oracle saw it. -The original report was fixed in #1902. The stronger oracle still found invalid updates and duplicate inserts. Each round forced me to spell out more of what collection change messages should guarantee, then teach the oracle to enforce it. +For [PR #2005](https://github.com/TanStack/db/pull/2005), an agent added a subscriber initialized with the current visible rows that validated each raw message, then compared its reconstructed rows with the independent model after every batch. The old code failed seven cases. The fix published each key once, and the stronger oracle went on to find another invalid insert when a pending delete overlapped an optimistic insert. Changing what the oracle could observe exposed failures that had previously been invisible. -This is how I pursue a whole class of bugs. I turn the report into a law, generate related histories, and check the public behavior at the point where a user or subscriber would notice the difference. I also test the instrument against the old implementation or a plausible wrong change. When another path reveals a blind spot, I expand what the oracle drives or observes. That stronger instrument stays in the repository for the next agent. +The original report was fixed in #1902. The later investigations required making the design more precise—and making the oracle capable of enforcing distinctions it had previously missed. -## Look for cranes +## A recipe for designing an oracle -I've been reading Daniel Dennett's [_Darwin's Dangerous Idea_](https://www.simonandschuster.com/books/Darwins-Dangerous-Idea/Daniel-C-Dennett/9780684824710). Darwin's startling claim, in Dennett's account, was that natural selection, with no foresight, could produce eyes, brains, and other astonishingly intricate adaptations. Many people doubted that a blind process could do this and looked for an outside intelligence to supply the design. Dennett calls that explanatory move a **skyhook**: it lifts the finished complexity into place from above, like the _deus ex machina_ of Greek theater, where stage machinery lowers a god to resolve a plot. To explain how complexity actually develops, we need mechanisms that work within the process. +Here's how I build one with my agents: -Dennett calls these evolutionary mechanisms **cranes**—construction cranes. Both skyhooks and cranes lift; the difference is that a crane works from solid support. It helps you reach upwards to build a new layer. Once that layer is built, it can support new cranes that reach higher and build further layers. In evolution, a crane makes more possibilities reachable for the next round of variation and selection. Sexual reproduction, for example, shuffles inherited variants into new combinations, opening paths that mutation in a single lineage would reach much more slowly. _The path to complexity runs through accumulating mechanisms to speedily explore and test the design space_. +1. **Choose one precise promise.** State what someone using the software should observe, and when. This is the oracle's law. Resolve ambiguous cases: our task-list model needs a rule for ordering tasks with equal priority. -The skyhook story in agentic programming is that a sufficiently intelligent model, given a repository, will infer every unstated rule and deliver the right system in one leap. One-shot coding makes that easy to believe for familiar tasks, but those successes stand on compilers, types, libraries, conventions, examples, tests, and a vast history of solved problems in the model's training. Every substantial software project runs into questions that history hasn't settled. Features interact in unexpected ways; new uses reveal missing guarantees; performance work opens up alternative implementations. There is no finished answer for an agent to retrieve. The work is to search the design space, decide what should hold, and test candidate answers. Agents need cranes that make that search productive and preserve what each investigation learns. +2. **Calculate the answer independently.** Derive it from the promise. Reusing production's algorithms or helpers can reproduce the same mistake on both sides and leave the oracle happily agreeing with broken code. -For agents working on DB itself, an oracle is a crane because it turns a reported failure into a repeatable search over a law. [Fast-check](https://fast-check.dev/) generates legal sequences of operations and shrinks a failure into a short counterexample. An agent can run proposed fixes and simpler implementations through the same instrument and see where their behavior diverges. The oracle makes many neighboring cases cheap to explore and bad candidates easy to reject. A more precise oracle gives me more freedom to try a simpler algorithm or a faster implementation; benchmarks tell me whether a performance experiment actually improved things. Those experiments can expose further gaps in what we've specified or verified. +3. **Choose where and when to observe production.** Compare the behavior at the moment the promise applies. For the collection oracle, that meant observing raw messages as subscribers received them, alongside the final rows. -I've set up the repository so a fresh agent can use these instruments without reconstructing months of design decisions. [Project guidelines](https://github.com/TanStack/db/blob/main/AGENTS.md) point it to the glossary, architecture documents, and [coverage map](https://github.com/TanStack/db/blob/main/docs/contributing/oracle-coverage.md), which identifies the oracle responsible for each behavior and its limits. The oracle files put the law beside the small model, generated histories, production path, and comparison, so an agent can read the promise and run an experiment in the same place. The [authoring](https://github.com/TanStack/db/blob/main/.agents/skills/oracle-authoring/SKILL.md) and [review](https://github.com/TanStack/db/blob/main/.agents/skills/oracle-review/SKILL.md) guides teach agents to strengthen that experiment; hostile reviewers follow the same paths to find plausible wrong implementations. A new session starts with a map of the system, runnable experiments, and ways to challenge the experiments themselves. +4. **Generate meaningful sequences.** Vary the data, operation order, and relevant timing. This draws on property-based testing and fuzzing (we use [fast-check](https://fast-check.dev/) extensively). Fast-check also shrinks failures into short counterexamples, making an otherwise bewildering failure practical to investigate. -Framework conformance tests and benchmarks add feedback for shared behavior and speed. I often use [TLA+](https://lamport.org/tla/tla.html) to explore potential changes to complex designs. +5. **Try to fool the oracle.** Deliberately break a rule in the implementation and verify that the oracle rejects it for the intended reason. Ask a hostile reviewer—an agent tasked with finding holes—which wrong designs could still pass. -I shape the _fitness landscape_ generally by editing the [AGENTS.md](https://github.com/TanStack/db/blob/main/AGENTS.md). For example I say "all PRs must be net negative for production code". This pushes agents hard to avoid bloated and duplicative implementations. +6. **Diagnose disagreements before changing expectations.** The implementation might violate the promise, the model might misstate it, or the promise itself might need redesign. Work out which account failed before deciding what to repair. Keep the shortened failing sequence as a regression case beside the model. -That extensive machinery I've developed matters because DB's API opened a huge design space. On-demand queries, pagination, persistence, optimistic writes, and synchronization meet in combinations we never enumerated when designing it. Together, these instruments help us build a richer theory of how clients should load, update, reconcile, and present data. +I've written and heavily iterated on [oracle-authoring](https://github.com/TanStack/db/blob/main/.agents/skills/oracle-authoring/SKILL.md) and [oracle-review](https://github.com/TanStack/db/blob/main/.agents/skills/oracle-review/SKILL.md) SKILLs, plus a rigorous [14-part rubric](https://github.com/TanStack/db/blob/main/docs/contributing/oracle-rubric.md) that agents use to evaluate and improve their oracles. -Paradoxically, the bug list keeps growing because our ability to find bugs keeps improving. Three months and many billions of tokens have produced more than a pile of fixes: agents now investigate DB with instruments that get sharper as they use them. That change in their working environment has mattered far more than any model upgrade I've seen. +### How this relates to formal verification -## Superhistory +For difficult designs, I often start in [TLA+](https://lamport.org/tla/tla.html), explore the consequences of proposed rules, then translate the model into a TypeScript oracle that runs against DB. -An afternoon with coding agents can compress what used to be weeks of software history. Venkatesh Rao calls this agent-mediated compression of experience [“artificial time”](https://contraptions.venkateshrao.com/p/superhistory-not-superintelligence). I spend much of the day in what feels like a succession of intense design meetings, with fresh evidence arriving 100x faster than I could have gathered it myself. +That model is an **executable specification**: a precise account of the intended behavior. This shares a foundation with [formal verification](https://www.anthropic.com/research/formal-verification). A formal proof, using a system such as [Lean](https://lean-lang.org/), establishes a specified property for all cases covered by its assumptions. Our generated tests exercise the actual implementation and compare its behavior with the specification. -Building software starts as an act of invention, but much of its maturation is discovery. DB's API created a world with rules whose consequences we didn't fully know. As users try it and agents probe its combinations, unexpected interactions reveal ambiguities, missing guarantees, and layers of architecture we hadn't anticipated. Some consequences follow from existing promises; others call for new rules. +## Look for cranes -That's what artificial time feels like from inside: questions that normally accumulate across years are arriving in months. Implementation work clears quickly, leaving me in a steady stream of design decisions. I spend much more of my day deciding what DB should guarantee and whether a fix simplifies the system or adds unnecessary machinery. Programming has become more intellectually demanding for me even as writing the code has become cheaper. +In Daniel Dennett's [_Darwin's Dangerous Idea_](https://www.simonandschuster.com/books/Darwins-Dangerous-Idea/Daniel-C-Dennett/9780684824710), Dennett chronicles Darwin's startling claim that natural selection, with no foresight, could produce eyes, brains, and other astonishingly intricate adaptations. Many people doubted that a blind process could do this and looked for an outside intelligence to supply the design, an explanatory move Dennett calls a **skyhook**: it lowers the finished complexity into place from above like the _deus ex machina_ of Greek theater, where stage machinery lowers a god to resolve the plot. -Artificial time changes the economics of rigor. Oracles add lots of rigor but are demanding to write and very verbose. Since this push began, DB has gained roughly 330,000 lines of tests—probably more code than I wrote in my entire life before AI. Agents make that work practical. +Dennett contrasts this with **cranes**—construction cranes. Both skyhooks and cranes lift, but a crane works from solid support. It helps you reach upwards to build a new layer. Once that layer is built, it can support new cranes that reach higher and build further layers. In evolution, cranes make more possibilities accessible to variation and selection. Sexual reproduction, for example, recombines inherited variants, letting selection work on combinations that mutation in a single lineage would reach much more slowly. -Expensive engineering doesn't always come with a business model that can fund it. Client-side infrastructure like DB can be useful to huge numbers of applications without offering an obvious way to charge for that value. Bringing the cost of implementation and design discovery down makes a thoroughly engineered framework possible on a much smaller budget. +The skyhook story in agentic programming is that a sufficiently intelligent model, given a repository, will infer every unstated rule and deliver the right system in one leap. One-shot coding makes that easy to believe for familiar tasks. Those successes stand on compilers, libraries, conventions, and a vast history of solved problems in the model's training. Much of the design work has already been done. -## What source code can't tell an agent +Every substantial software project runs into questions that history hasn't settled. Features interact in unexpected ways; new uses reveal missing guarantees. More intelligence cannot reconstruct a decision we haven't made or captured. The work is to search the design space, decide what should hold, and test candidate answers. -A codebase is an incomplete account of the software we want to build. It records what the implementation does today, but doesn't reliably tell an agent which behaviors are promises, which are accidents, or why I chose one rule over another. More intelligence cannot reconstruct a decision we haven't made or captured. +For my agent swarms, the cranes make that search productive. Oracles make candidate implementations cheap to try and incorrect behavior easier to reject. Hostile reviews strengthen the instruments doing the rejecting. Benchmarks tell me whether an implementation that preserves the behavior also improves performance. Together, these mechanisms let agents explore more ambitious changes and get useful feedback about which ones to pursue. -Design develops through many successive adaptations. Each decision has to fit what's already there, and its consequences reveal further questions to work through. Programmers have always drawn on accumulated design knowledge to make those decisions—recognizing parallels, adapting ideas, and discovering where they stop fitting. LLMs give coding agents a super fast search interface into that history. I use them to explore how those ideas apply to DB's particular problems and gradually develop a more complete and coherent design. This has become the bulk of programming for me. +I also shape the _fitness landscape_—the constraints and feedback that favor some candidates over others—by editing [AGENTS.md](https://github.com/TanStack/db/blob/main/AGENTS.md). For example, I tell agents to treat every line of production code as a continuing cost and prefer fixes that remove code. This pushes them hard to avoid bloated and duplicative implementations. -Design is immensely complicated. Establishing or improving a single oracle can take hours of investigation between me and my agents: figuring out which distinctions matter, what the system should promise, and whether our model actually expresses that promise. A small executable model can embody a great deal of intellectual work. Those 176 oracle files represent a huge accumulated investment in understanding how this framework should behave. +The layering matters. A stronger oracle lets an agent attempt a change that would previously have been difficult to verify. That investigation can expose another missing distinction, which becomes part of the model and opens further possibilities. The cranes help build the next layer, which supports the next cranes. -Each oracle distills a small part of DB's behavior into an explicit model, with the reasoning behind its rules written beside it. Verifying implementations is one powerful use of that account; helping future programmers and agents understand and extend the system is another. +The work has taken three months and many billions of tokens. Each investigation leaves later agents with sharper instruments. That change in their working environment has mattered far more than any model upgrade I've seen. -An agent working on a change will often run afoul of an oracle and get told its design is wrong. It then reads the oracle carefully to understand the design it needs to respect and revises its approach. Hours of earlier design work guide a later agent at the moment it needs that understanding. +## Superhistory -Design that can talk back. +Coding agents can compress what used to be weeks of work into an afternoon. Venkatesh Rao calls this agent-mediated compression of experience [“artificial time”](https://contraptions.venkateshrao.com/p/superhistory-not-superintelligence). I spend much of the day in what feels like a succession of intense design meetings, with fresh evidence arriving 100x faster than I could have gathered it myself. -## The world DB creates for your agents +Questions that normally accumulate across years are arriving in months. Implementation work clears quickly, leaving me in a steady stream of design decisions. I spend much more of my day deciding what DB should guarantee and whether a fix simplifies the system or adds unnecessary machinery. Programming has become more intellectually demanding for me even as writing the code has become cheaper. + +When an idea would take weeks to investigate, I need a strong reason to try it. With agents and an oracle, I can afford to take a much less certain idea far enough to find out whether it works. That changes which designs I can explore. + +Rigorous engineering is much cheaper now. Oracles work incredibly well, but they're demanding to write and very verbose. In the months spent preparing DB for 1.0, the repository has gained roughly 330,000 lines of tests—probably more code than I wrote in my entire life before AI. Agents make that work practical. -Good programming abstractions create smaller, more consistent worlds for the code above them. A filesystem gives programs files and paths instead of disk sectors. TCP gives them an ordered stream even when the network drops or reorders packets. A programming language gives them functions and types instead of registers and jump instructions. Each settles a mass of lower-level questions so the next layer can make more ambitious moves. +## Drawing out the design -DB creates a simpler world for client data for application developers and their agents. An agent building an application can work with typed collections backed by TanStack Query over an existing API, a sync engine, or local persistence. It can join issues with projects, show one team's open work, and edit optimistically without building a separate endpoint and cache path for every screen. DB keeps the live results current while handling on-demand fetching, pagination, and reconciliation with the server. +Programmers have always drawn on accumulated design knowledge—recognizing parallels, adapting ideas, and discovering where they stop fitting. LLMs give coding agents a super fast search interface into that history. I use them to search a vast repertoire of algorithms and design ideas for things that fit DB's particular problems, then work through the adaptations those ideas need. -For that world to exist, DB must deliver on its guarantees. A joined, filtered view stays current as its underlying records change. An optimistic edit appears immediately, then remains when persistence succeeds or rolls back when it fails. With on-demand sync, the query can shape backend requests so a screen loads only the rows it needs. Those promises still have to hold when pagination, offline persistence, and server updates interact—and at the speed a demanding application needs. The last three months of work have been about making this simplified world reliable enough to build on. +Design develops through many successive adaptations. Each decision has to fit what's already there, and its consequences reveal further questions to work through. An idea that solves one problem can expose a distinction we hadn't previously needed, or a conflict between two otherwise useful rules. Working through those decisions and distilling them into oracle models has become the bulk of programming for me. -When you start a new application, you can experiment more freely by building on DB's mature data mechanics. You and your agents can focus on behaviors you want to create instead of rebuilding query, cache, and sync behavior for each screen. +Design is immensely complicated. Establishing or improving a single oracle can take hours of investigation between me and my agents: figuring out which distinctions matter, what the system should promise, and whether our model actually expresses that promise. A small executable model can embody a great deal of intellectual work. Together, those models embody an increasingly detailed theory of how clients should load, update, reconcile, and present data. -Frameworks, infrastructure, and developer tools embody detailed theories of their domains. Their APIs shape applications; that knowledge can also guide the agents writing them. [SKILLs](https://agentskills.io/home) are a first step. The oracles I've described verify DB itself. DB should also provide oracles for custom collections, so developers and their agents can verify that they sync data correctly and get a short failing history when they don't. +## The world DB creates for your agents + +All this design work gives an agent building your application a simpler world to work in. It can join issues with projects, show one team's open work, and edit optimistically through DB's collections and live queries. DB keeps the results current and handles data loading, persistence, and synchronization, leaving you and your agents to focus on the behaviors you want to create. -The framework can also supply instruments for application-specific requirements. DB could expose how much data a query loads or how often it refreshes; an application could set the budgets that matter for its users. The framework supplies the instruments, and the application supplies the requirements. Agents then have both explicit expectations and evidence to guide their changes. +Frameworks, infrastructure, and developer tools all do this: they embody detailed theories of their domains and make those domains easier to work in. Their APIs already shape applications. With coding agents, that knowledge can also guide how application code gets written. [SKILLs](https://agentskills.io/home) are a first step: they let a framework explain which abstractions to use, what those abstractions guarantee, and where the application has a decision to make. -These are cranes for userland: mechanisms that work inside the application-building process, helping agents explore and construct the next layer on top of a framework. The next generation of frameworks, infrastructure, and developer tools will create rich, lawful, playable worlds for applications and equip coding agents to build within them. +For DB, I want to put that accumulated design knowledge in your agents' hands: oracles and other cranes that help them turn ambitious ideas into applications that hold up in practice. An agent building a custom collection should be able to run an oracle to verify that it syncs correctly. An agent tuning a screen should have instruments to optimize query loading speed and minimize data on the wire. You set the requirements; DB should work with your agents to translate your intent into optimal code. -Here's another idea we're exploring for where to take TanStack DB next: write ordinary server functions to query and mutate Postgres, and DB compiles them into the collections and actions your client uses. +### From server functions to live collections + +The instruments built while hardening DB also make more ambitious abstractions practical to pursue. One idea I'm exploring is to let you write ordinary server functions to query and mutate Postgres, then have DB compile them into the collections and actions your client uses. ```tsx // Server: define a query @@ -152,12 +205,14 @@ addTodo({ id: crypto.randomUUID(), text: 'Hello world' }) _Simplified sketch of an experimental API._ -DB also generates the data-loading and mutation wiring. When a mutation runs, the client tells the server which query collections are live. The server determines which need updating and returns fresh results with the mutation response. +In this design, DB also generates the data-loading and mutation wiring. When a mutation runs, the client tells the server which query collections are live. The server determines which need updating and returns fresh results with the mutation response. + +Making this work broadly means understanding enough of Postgres's vast language to preserve query meaning, determine which reads a write affects, and reconcile client state correctly. A few years ago, I wouldn't have considered attempting the larger project. The work of the last three months has made it tractable enough to pursue. -Making this work broadly means understanding enough of Postgres's vast language to preserve query meaning, determine which reads a write affects, and reconcile client state correctly. A few years ago, I wouldn't have considered attempting the larger project. The last three months have changed the economics: agents can explore that space, find where the design breaks, and carry stronger instruments into the next investigation. That makes an extraordinarily demanding abstraction tractable enough to pursue. +### Building the next layer There's a useful name for what these cranes improve: _evolvability_, a system's capacity to support further useful development. Autonomy asks how much work an agent can do without me. Evolvability asks what new work becomes possible because of what we've learned. An agent arriving tomorrow can attempt something more ambitious using the same LLM because it inherits better cranes. My days are full of decisions about what matters, which promises to make, and when an investigation has gone far enough. Each answer can become part of the machinery that makes further development possible. That's what makes me excited about where programming is going: the possibility of much more robust, delightful, and varied software, including ideas that used to cost too much to pursue. -I began this push with a finite bug list. TanStack DB 1.0 RC1 is the result so far. [Try it](https://tanstack.com/db/latest/docs/quick-start) in a demanding application and tell us [what breaks](https://github.com/TanStack/db/issues) or [what DB makes needlessly hard to build](https://github.com/TanStack/db/discussions). Those reports are how the next layer of design begins. +I began by trying to fix every known DB bug. TanStack DB 1.0 RC1 is the result so far. [Try it](https://tanstack.com/db/latest/docs/quick-start) in a demanding application and tell us [what breaks](https://github.com/TanStack/db/issues) or [what DB makes needlessly hard to build](https://github.com/TanStack/db/discussions).