Skip to content

feat(db): live query without fetching - #2179

Open
jchook wants to merge 13 commits into
TanStack:mainfrom
jchook:feat/local-live-query
Open

jchook wants to merge 13 commits into
TanStack:mainfrom
jchook:feat/local-live-query

Conversation

@jchook

@jchook jchook commented Oct 15, 2026 •

Copy link
Copy Markdown

🎯 Changes

Add autoLoad: false to live-query configuration to query data already in collections without fetching or syncing. Results remain reactive, with filtering, joins, and pagination handled by the existing query engine.

One use case is application-owned fetching. Some remote API requests cannot be derived correctly from the query IR. Applications need to construct those requests themselves and ingest the results into collections, without the live query triggering additional requests.

Implementation Details

Making loadSubset a no-op is not sufficient:

  • Source sync starts automatically on subscription and can fetch independently of loadSubset. This is also suppressed when autoLoad is disabled.
  • The ready state normally depends on data loading. With autoLoad: false, it indicates that the available rows have been evaluated, even if the collection is empty.
  • Joins and pagination can request additional subsets or ordered pages. These requests are disabled, and the query runs over the available matching rows.

autoLoad defaults to true. Queries with different settings have separate identities, including with explicit query keys. Collection data remains shared, so updates from other queries or application code still appear in the results.

✅ Checklist

  • I have tested this code locally with pnpm test.

🚀 Release Impact

  • This change affects published code, and I have generated a changeset.
  • This change is docs/CI/dev-only (no release).

Related discussion

Summary by CodeRabbit

  • New Features

    • Added an autoLoad option for live queries and React query hooks. When disabled, queries observe and react to rows already available in their collections without starting source loading.
    • Queries can become ready based on available rows, independently of source loading. Switching between automatic and local observation uses a separate query identity; infinite-query pages reset when the mode changes.
    • Documented how readiness, pagination, errors, and shared source loading behave with automatic loading disabled.
  • Tests

    • Added coverage for local observation across joins, windows, includes, loading states, and React hooks.

@changeset-bot

changeset-bot Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: aee450a

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 33 packages
Name Type
@tanstack/db Minor
@tanstack/react-db Minor
@tanstack/angular-db Patch
@tanstack/capacitor-db-sqlite-persistence-e2e-app Patch
@tanstack/db-sqlite-persistence-core Patch
@tanstack/electric-db-collection Patch
@tanstack/expo-db-sqlite-persistence-e2e-app Patch
@tanstack/offline-transactions Patch
@tanstack/powersync-db-collection Patch
@tanstack/query-db-collection Patch
@tanstack/rxdb-db-collection Patch
@tanstack/solid-db Patch
@tanstack/svelte-db Patch
@tanstack/tauri-db-sqlite-persistence-e2e-app Patch
@tanstack/trailbase-db-collection Patch
@tanstack/vue-db Patch
todos Patch
offline-transactions-react-native Patch
shopping-list-react-native Patch
@tanstack/db-example-react-next-ssr-e2e Patch
@tanstack/db-example-paced-mutations-demo Patch
offline-first-electron Patch
@tanstack/db-example-react-action-enforcement Patch
@tanstack/db-example-react-start-ssr-e2e Patch
@tanstack/db-example-react-todo Patch
@tanstack/browser-db-sqlite-persistence Patch
@tanstack/capacitor-db-sqlite-persistence Patch
@tanstack/cloudflare-durable-objects-db-sqlite-persistence Patch
@tanstack/electron-db-sqlite-persistence Patch
@tanstack/expo-db-sqlite-persistence Patch
@tanstack/node-db-sqlite-persistence Patch
@tanstack/react-native-db-sqlite-persistence Patch
@tanstack/tauri-db-sqlite-persistence Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai

coderabbitai Bot commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 2f6f41e2-95ac-4f3b-935a-91ebe999f762
📥 Commits

Reviewing files that changed from the base of the PR and between eb739d7 and aee450a.

📒 Files selected for processing: 5
  • packages/db/src/live-query-options.ts
  • packages/db/src/query/live/collection-config-builder.ts
  • packages/db/src/query/live/collection-subscriber.ts
  • packages/react-db/src/useLiveInfiniteQuery.ts
  • packages/react-db/src/useLiveQuery.ts
🚧 Files skipped from review as they are similar to previous changes: 5
  • packages/db/src/query/live/collection-subscriber.ts
  • packages/react-db/src/useLiveQuery.ts
  • packages/db/src/query/live/collection-config-builder.ts
  • packages/db/src/live-query-options.ts
  • packages/react-db/src/useLiveInfiniteQuery.ts

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 6 remain after this review.

📝 Walkthrough

Live queries can use autoLoad: false to evaluate available source rows without initiating acquisition. The change adds collection and React hook support, distinguishes loading modes in query identities, and adds oracle and integration tests plus documentation.

Changes: Local Live Query Loading

Layer / File(s) Summary
Configuration and query identity
.changeset/local-query-observation.md, docs/guides/live-queries.md, packages/db/src/query/live/types.ts, packages/db/src/types.ts, packages/db/src/live-query-options.ts
Adds the autoLoad option, recognizes live-query configuration objects, and distinguishes disabled-loading queries in query identity. The guide describes readiness, errors, pagination, and shared-source behavior.
Observe rows without acquisition
packages/db/src/collection/changes.ts, packages/db/src/collection/subscription.ts, packages/db/src/query/live/collection-config-builder.ts, packages/db/src/query/live/collection-subscriber.ts, packages/db/src/query/live/ARCHITECTURE.md
When loading is disabled, subscriptions retain detached demands without acquiring source data. Live queries observe available rows and determine readiness from query evaluation rather than provider readiness.
React hook mode and identity
packages/react-db/src/useLiveInfiniteQuery.ts, packages/react-db/src/useLiveQuery.ts, packages/react-db/tests/live-query-auto-load.test.tsx
React hooks track autoLoad when creating and reusing collections. Tests cover identity changes, local updates, Suspense separation, and infinite-query page resets when the mode changes.
Oracle and integration validation
packages/db/tests/live-query-auto-load-oracle.test.ts, packages/db/tests/oracle-config.ts, packages/db/package.json, packages/query-db-collection/tests/live-query-auto-load.test.ts, docs/contributing/oracle-coverage.md, docs/contributing/oracle-reviews/2026-10-14-local-live-query.md
Adds property-based coverage across source modes, index states, and query shapes, plus a Query Collection integration test. Registers the oracle and records coverage scope and validation results.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Feature

Sequence Diagram(s)

sequenceDiagram
  participant useLiveQuery
  participant LiveQueryCollection
  participant CollectionSubscriber
  participant SourceCollection
  participant QueryPipeline
  useLiveQuery->>LiveQueryCollection: Create query with autoLoad false
  LiveQueryCollection->>CollectionSubscriber: Subscribe to source changes
  CollectionSubscriber->>SourceCollection: Subscribe without automatic acquisition
  SourceCollection-->>CollectionSubscriber: Emit available row changes
  CollectionSubscriber->>QueryPipeline: Forward row changes for evaluation
Loading
Merge Risk: ⚪ Minimal · up to aee45

The reviewed loading-mode behavior has no identified issue that needs resolution before merging.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 71.43% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 14 functions across 13 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Title check Passed The title clearly and concisely describes the main change: live queries can operate without fetching.
Description check Passed The description includes the required Changes, Checklist, and Release Impact sections. It explains the motivation, implementation behavior, testing, and changeset status.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@jchook jchook changed the title Feat/local live query feat(db): autoLoad: false Oct 15, 2026
@jchook jchook changed the title feat(db): autoLoad: false feat(db): live query without fetching Oct 15, 2026
@jchook
jchook marked this pull request as ready for review October 16, 2026 01:19
@KyleAMathews

Copy link
Copy Markdown
Collaborator

Couldn't you use local collections for data you're loading in some other way?

@jchook

jchook commented Oct 16, 2026 •

Copy link
Copy Markdown
Author

Couldn't you use local collections for data you're loading in some other way?

In our case, we can translate the TanStack DB query into the right remote API request about 90% of the time. For the remaining cases, we need a custom request whose results we ingest into the same shared collections.

We still want TanStack’s local query evaluation and reactivity in those cases, but without also triggering loadSubset. So the distinction is per query. The same collection needs to support both automatic loading and custom fetching. Making the collections local-only would mean giving up automatic loading for the 90% that already works.

We could move all acquisition into our own wrapper over local collections, but then we’d need to reproduce the query-to-demand planning TanStack already handles, including joins and pagination. Ideally, we’d keep that machinery for supported queries and opt out of automatic acquisition only when supplying a custom fetch.

@robertf224

Copy link
Copy Markdown

@KyleAMathews fwiw I'm also looking for something like this for two use-cases:

  • devtools panel where I want to be able to let you inspect all the data on device (either in memory or persistence) without triggering new data loading
  • Zero-style outbox implementation where you can write async mutators that do tanstack db queries inside to fetch data (thru queryOnce), and current visible state = server state + replayed outbox (so when an outbox entry is confirmed you roll the whole thing back, remove that entry, and replay again. good explanation in here). when we run those mutators on the server it should fetch data over the network, when we run them on the client it should only fetch against memory/persistence

Prior art here is something like fetch policies in Relay, would be nice to get like a localOnly flag you can pass alongside the query to queryOnce, useLiveQuery, etc.

@KyleAMathews

Copy link
Copy Markdown
Collaborator

Robert feel free to open feature request issues for these.

@jchook so for the other 10% how do you load data? Some sort of background job thing? I'm confused still how your app works.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants