Skip to content

staleTime is ignored for syncMode: "on-demand" collections — queries are reused instead of refetched #998

@delphinaubin

Description

@delphinaubin

Describe the bug
When using a collection configured with:

  • syncMode: "on-demand"
  • staleTime: 0

the expected behavior is that queries should always be refetched, since stale time 0 means results are immediately stale.

However, the actual behavior is that previous query results are reused, and the queryFn is not executed again when navigating back to a previously fetched item. This reproduces consistently and prevents proper on-demand refetching.

I also tested other staleTime values (10, 50, 5000, etc.), and the stale time was never honored. The query cache is reused in all cases.

To Reproduce
I created a minimal reproduction repository here:

https://github.com/delphinaubin/tanstack-db-sync-on-demand-collection-issue

And the code sandbox link: https://githubbox.com/delphinaubin/tanstack-db-sync-on-demand-collection-issue

Below is the relevant code snippet:

import {createCollection, parseLoadSubsetOptions} from "@tanstack/db";
import {queryCollectionOptions} from "@tanstack/query-db-collection";
import {QueryClient} from "@tanstack/query-core";

let todoLoadCallCount = 0;

// Loader increments a counter so we can detect whether the query actually ran.
const loadTodoById = (todoId: number) =>
  Promise.resolve([
    {
      id: todoId,
      name: `TODO ${todoId} – load #${todoLoadCallCount++}`,
    },
  ]);

export const queryClient = new QueryClient();

export const todosCollection = createCollection(
  queryCollectionOptions({
    queryClient,
    queryKey: ["todos"],
    syncMode: "on-demand",

    // Expected: force refetch every time.
    staleTime: 0,

    queryFn: (ctx) => {
      const options = parseLoadSubsetOptions(ctx.meta?.loadSubsetOptions);
      // We look for a simple "id = <value>" filter
      const idFilter = options.filters.find(
        (filter) =>
          filter.field.length === 1 &&
          filter.field[0] === "id" &&
          filter.operator === "eq",
      );

      const todoId = idFilter?.value ?? 1;

      // This *should* run every time the query is accessed.
      return loadTodoById(todoId);
    },

    getKey: (item) => item.id,
  }),
);

Expected Behavior

With staleTime = 0, the query should always refetch, similar to TanStack Query semantics.

queryFn should run on every access.

todoLoadCallCount should increment every time.

Actual Behavior

The query result is reused even with staleTime = 0.

The queryFn does not run again when returning to a previously fetched query.

staleTime appears to be ignored entirely in syncMode: "on-demand" collections.

Environment

  • @tanstack/db: 0.5.11
  • @tanstack/query-db-collection: 1.0.6
  • @tanstack/query-core: 5.90.12
  • Browser: Tested on Chrome 143.0.7499.41 and Safari 26.1
  • OS: macOS Sequoia v15.7.2

Additional context

I tested multiple staleTime values (0, 10, 50, 5000), and none were applied.

The problem seems isolated to sync: on-demand collections.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions