# TanStack/query — codebase unpack

> Canonical page: https://codevetter.com/unpack/query

This is a deterministic Repo Unpack scan of TanStack/query — a structural map, not a review, security audit, or maintainer-endorsed description.

- Scanned commit: 29859ae60c8dca0a5cdbf8abccc775b655cf43e2 (2026-10-02)
- Last upstream commit: ci: Version Packages (#11806)
- Generated by codevetter 1.15.0 on 2026-10-02
- 3553 files scanned · 11.7 MB

Source inspection; upstream code and tests were not executed.

## Languages

- Markdown: 1766 files
- TypeScript: 991 files
- JSON: 307 files
- JavaScript: 174 files
- Svelte: 86 files
- HTML: 78 files
- Vue: 20 files
- CSS: 19 files

## Repository structure

- docs/ — 1660 files
- packages/ — 946 files
- examples/ — 803 files
- integrations/ — 102 files
- .github/ — 10 files
- scripts/ — 7 files
- media/ — 2 files
- .nx/ — 1 files

Probable source entrypoint: `packages/` (inferred from the tree, not upstream docs)

## Package

- package.json: root — 33 declared dependencies

## Structural health signals

Average score 6.9/10 across 96 files; 34 hotspots. These are deterministic review leads, not proof of a bug.

## Recent history

- 29859ae60c8d (2026-10-02) ci: Version Packages (#11806)
- ec060b6f74b2 (2026-10-02) fix(query-devtools): isolate signals on devtools instances (#11799)
- 94e20031dd0a (2026-10-02) test(lit-query/createQueryController): add test for removing the observer from the query when destroyed (#11804)
- d49c1f588591 (2026-10-02) test(lit-query/useMutationState): add test for returning the current mutation states when connected after a mutation started (#11803)
- d547e2195dfd (2026-10-02) test(lit-query/createQueriesController): add test for not having stale closures with 'combine' (#11802)

## Overview

TanStack Query is a TypeScript library for application developers who need to fetch, cache, synchronize, and update asynchronous server state across UI frameworks. Its framework-independent QueryClient, caches, retry machinery, and observers power framework adapters, with optional persistence, hydration, cross-tab synchronization, developer tools, and ESLint rules. This brief investigates commit 29859ae60c8dca0a5cdbf8abccc775b655cf43e2 through bounded source inspection, including concrete startup, fetch, mutation, and persistence flows.

## System map

The repository distributes libraries rather than one deployed application. Query-core supplies state ownership and execution primitives; framework packages translate those primitives into framework lifecycle and reactivity. Persistence and broadcast packages introduce optional storage and messaging boundaries, while developer tools observe and manipulate the same caches. The inspected workspace uses pnpm and Nx, with package builds and Changesets publication.
- The root is a private ESM workspace pinned to pnpm@12.4.2; workspace membership includes packages, integrations, and framework examples, with Vue 2 and Nuxt examples excluded. — [package.json#L1-L12](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/package.json#L1-L12) [pnpm-workspace.yaml#L63-L74](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/pnpm-workspace.yaml#L63-L74)
- Query-core's public entrypoint exports QueryClient, QueryCache, MutationCache, observers, hydration, managers, cancellation types, and experimental_streamedQuery. — [packages/query-core/src/index.ts#L3-L47](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/index.ts#L3-L47)
- QueryClient creates or accepts QueryCache and MutationCache instances and owns client defaults, key-specific default registries, and lifecycle subscriptions. — [packages/query-core/src/queryClient.ts#L79-L119](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/queryClient.ts#L79-L119)
- React connects observers through useSyncExternalStore; Vue computes unwrapped options and updates reactive state; Svelte uses runes and observer subscriptions with lifecycle cleanup. — [packages/react-query/src/useBaseQuery.ts#L83-L116](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/react-query/src/useBaseQuery.ts#L83-L116) [packages/vue-query/src/useBaseQuery.ts#L98-L158](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/vue-query/src/useBaseQuery.ts#L98-L158) [packages/svelte-query/src/createBaseQuery.svelte.ts#L33-L101](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/svelte-query/src/createBaseQuery.svelte.ts#L33-L101)
- Runtime caches are in memory: QueryCache constructs a Map keyed by query hash, while MutationCache constructs a mutation Set and a scope-to-mutations Map. — [packages/query-core/src/queryCache.ts#L123-L129](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/queryCache.ts#L123-L129) [packages/query-core/src/mutationCache.ts#L124-L134](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/mutationCache.ts#L124-L134)
- Network execution is delegated to application queryFn and mutationFn callbacks; the offline example implements fetch requests and MSW handlers outside query-core. — [packages/query-core/src/query.ts#L649-L679](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/query.ts#L649-L679) [packages/query-core/src/mutation.ts#L295-L314](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/mutation.ts#L295-L314) [examples/react/offline/src/api.ts#L17-L44](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/examples/react/offline/src/api.ts#L17-L44)
- Root test:pr runs affected Nx checks, test:ci runs checks across projects, and build:all excludes examples and integrations; Nx orders dependency compilation and build targets. — [package.json#L15-L29](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/package.json#L15-L29) [nx.json#L28-L34](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/nx.json#L28-L34) [nx.json#L60-L85](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/nx.json#L60-L85)
- Published core packages expose ESM, CommonJS, declarations, and source conditions; shared tsdown factories generate modern and legacy bundles, and the release workflow builds before Changesets publication. — [packages/query-core/package.json#L33-L56](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/package.json#L33-L56) [scripts/getTsdownConfig.js#L8-L39](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/scripts/getTsdownConfig.js#L8-L39) [.github/workflows/release.yml#L34-L56](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/.github/workflows/release.yml#L34-L56)

## Feature catalog

The public product is a family of APIs for server-state management. Inspected features include reactive and imperative queries, mutations, pagination, background refresh, streaming, and server/client hydration. Persistence and cross-tab synchronization are optional integrations. Developer tools and lint rules support application debugging and API usage.
- React exports useQuery, useQueries, Suspense query variants, prefetch hooks, useInfiniteQuery, mutation hooks, activity indicators, providers, and option factories. — [packages/react-query/src/index.ts#L8-L26](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/react-query/src/index.ts#L8-L26) [packages/react-query/src/index.ts#L32-L56](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/react-query/src/index.ts#L32-L56)
- queryClient.query resolves stale data through fetch or returns fresh cached data, then applies optional select; infiniteQuery marks options as infinite and delegates to query. — [packages/query-core/src/queryClient.ts#L580-L604](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/queryClient.ts#L580-L604) [packages/query-core/src/queryClient.ts#L690-L697](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/queryClient.ts#L690-L697)
- Queries support dependent execution through enabled or skipToken, initial data, selected results, and previous-page placeholders through keepPreviousData. — [packages/react-query/src/useQuery.ts#L164-L224](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/react-query/src/useQuery.ts#L164-L224) [packages/react-query/src/useQuery.ts#L226-L283](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/react-query/src/useQuery.ts#L226-L283) [packages/query-core/src/queryClient.ts#L1051-L1053](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/queryClient.ts#L1051-L1053)
- Background refresh supports mount, focus, reconnect, and interval triggers; interval fetching respects enabled/server checks and focus unless refetchIntervalInBackground is enabled. — [packages/query-core/src/queryObserver.ts#L478-L483](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/queryObserver.ts#L478-L483) [packages/query-core/src/queryObserver.ts#L510-L536](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/queryObserver.ts#L510-L536) [packages/query-core/src/queryObserver.ts#L847-L873](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/queryObserver.ts#L847-L873)
- Infinite queries fetch forward or backward using page-parameter callbacks, maintain pages and pageParams together, stop when subsequent parameters are nullish, and bound retained pages through maxPages. — [packages/query-core/src/infiniteQueryBehavior.ts#L40-L107](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/infiniteQueryBehavior.ts#L40-L107)
- Mutations expose fire-and-forget mutate and promise-returning mutateAsync, optimistic lifecycle callbacks, and serialization for mutations sharing scope.id. — [packages/react-query/src/useMutation.ts#L224-L245](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/react-query/src/useMutation.ts#L224-L245) [packages/query-core/src/mutation.ts#L319-L383](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/mutation.ts#L319-L383) [packages/query-core/src/mutationCache.ts#L195-L224](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/mutationCache.ts#L195-L224)
- Optional state portability includes hydrate/dehydrate, storage-backed cache persistence, cross-tab broadcasts, and streamed AsyncIterable accumulation with reset, append, or replace refetch modes. — [packages/query-core/src/hydration.ts#L208-L245](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/hydration.ts#L208-L245) [packages/query-persist-client-core/src/persist.ts#L71-L88](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-persist-client-core/src/persist.ts#L71-L88) [packages/query-broadcast-client-experimental/src/index.ts#L49-L73](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-broadcast-client-experimental/src/index.ts#L49-L73) [packages/query-core/src/streamedQuery.ts#L9-L20](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/streamedQuery.ts#L9-L20)
- Devtools provides query/mutation views, filtering and sorting state, offline controls, and JSON cache editing; the ESLint plugin provides eight registered rules with recommended and stricter configurations. — [packages/query-devtools/src/Devtools.tsx#L674-L735](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-devtools/src/Devtools.tsx#L674-L735) [packages/query-devtools/src/Devtools.tsx#L2302-L2334](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-devtools/src/Devtools.tsx#L2302-L2334) [packages/eslint-plugin-query/src/rules.ts#L20-L29](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/eslint-plugin-query/src/rules.ts#L20-L29) [packages/eslint-plugin-query/src/index.ts#L17-L30](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/eslint-plugin-query/src/index.ts#L17-L30)

## Data flow

Keys and options enter through adapters or QueryClient methods and resolve into shared cache entries. Application callbacks produce raw data, while observers derive presentation results and notify framework subscribers. Mutations retain variables and optimistic context separately from query data. Hydration, persistence, and broadcast transfer snapshots across explicit external boundaries.
- defaultQueryOptions merges client query defaults, matching key defaults, and caller options in that order; it computes a missing queryHash and derives reconnect, Suspense-error, persister-network, and skipToken defaults. — [packages/query-core/src/queryClient.ts#L1024-L1053](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/queryClient.ts#L1024-L1053)
- hashQueryKeyByOptions chooses queryKeyHashFn or hashKey; the default hash JSON-stringifies keys with sorted plain-object properties, and QueryCache.build reuses an entry by that hash. — [packages/query-core/src/utils.ts#L267-L295](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/utils.ts#L267-L295) [packages/query-core/src/queryCache.ts#L159-L177](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/queryCache.ts#L159-L177)
- Query.fetch constructs callback context containing client, queryKey, meta, and a consumed-signal getter; an optional persister wraps queryFn and a behavior hook can replace fetchFn before retry execution. — [packages/query-core/src/query.ts#L634-L712](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/query.ts#L634-L712)
- Successful fetch data passes through replaceData and a success dispatch; the reducer updates timestamps and status, then notifies a stable observer snapshot and cache subscribers. — [packages/query-core/src/query.ts#L312-L326](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/query.ts#L312-L326) [packages/query-core/src/query.ts#L848-L863](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/query.ts#L848-L863) [packages/query-core/src/query.ts#L892-L902](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/query.ts#L892-L902) [packages/query-core/src/utils.ts#L460-L482](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/utils.ts#L460-L482)
- QueryObserver derives placeholder and selected data without replacing raw query state; select results are memoized, selector exceptions become observer errors, and property tracking filters listener notifications. — [packages/query-core/src/queryObserver.ts#L610-L684](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/queryObserver.ts#L610-L684) [packages/query-core/src/queryObserver.ts#L753-L784](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/queryObserver.ts#L753-L784)
- MutationObserver.mutate builds a new Mutation for supplied variables; Mutation.execute stores the onMutate result as context and supplies variables, context, and function metadata to lifecycle callbacks. — [packages/query-core/src/mutationObserver.ts#L207-L221](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/mutationObserver.ts#L207-L221) [packages/query-core/src/mutation.ts#L289-L345](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/mutation.ts#L289-L345) [packages/query-core/src/mutation.ts#L348-L380](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/mutation.ts#L348-L380)
- persistQueryClientSave packages buster, timestamp, and dehydrated state; the async storage adapter serializes that envelope and writes it through caller-provided storage, while restore reads and deserializes the same key. — [packages/query-persist-client-core/src/persist.ts#L113-L125](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-persist-client-core/src/persist.ts#L113-L125) [packages/query-async-storage-persister/src/index.ts#L42-L59](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-async-storage-persister/src/index.ts#L42-L59) [packages/query-async-storage-persister/src/index.ts#L84-L94](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-async-storage-persister/src/index.ts#L84-L94)
- Broadcast sends successful updates, additions, and removals with observers; incoming messages set or build query state inside an echo-suppression transaction, and cleanup unsubscribes and closes the channel. — [packages/query-broadcast-client-experimental/src/index.ts#L112-L146](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-broadcast-client-experimental/src/index.ts#L112-L146) [packages/query-broadcast-client-experimental/src/index.ts#L148-L197](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-broadcast-client-experimental/src/index.ts#L148-L197)

## Behavior traces

The investigation followed startup, primary fetch, optimistic mutation, and persistent restoration through concrete source files. These are source execution traces rather than observed runtime recordings. Each trace retains important conditional branches, including stale-cache reuse, restoration gating, cancellation, and scope queues. The offline example supplies an application-level path connecting these library mechanisms.
- Offline example startup calls worker.start, resolves #root, and renders App; App supplies its configured client and localStorage persister to PersistQueryClientProvider. — [examples/react/offline/src/index.tsx#L1-L14](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/examples/react/offline/src/index.tsx#L1-L14) [examples/react/offline/src/App.tsx#L24-L47](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/examples/react/offline/src/App.tsx#L24-L47) [examples/react/offline/src/App.tsx#L58-L73](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/examples/react/offline/src/App.tsx#L58-L73)
- Provider lifecycle runs QueryClientProvider's effect → client.mount → focusManager/onlineManager subscriptions; positive events await resumePausedMutations before notifying the query cache, and the last unmount removes subscriptions. — [packages/react-query/src/QueryClientProvider.tsx#L70-L85](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/react-query/src/QueryClientProvider.tsx#L70-L85) [packages/query-core/src/queryClient.ts#L104-L135](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/queryClient.ts#L104-L135)
- React query flow runs useQuery → useBaseQuery → useQueryClient/defaultQueryOptions → new QueryObserver → getOptimisticResult → useSyncExternalStore subscription; restoring or subscribed:false prevents that subscription. — [packages/react-query/src/useQuery.ts#L296-L298](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/react-query/src/useQuery.ts#L296-L298) [packages/react-query/src/useBaseQuery.ts#L51-L89](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/react-query/src/useBaseQuery.ts#L51-L89) [packages/react-query/src/useBaseQuery.ts#L91-L116](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/react-query/src/useBaseQuery.ts#L91-L116)
- The first observer subscriber runs addObserver → shouldFetchOnMount → executeFetch → Query.fetch → retryer.start → queryFn; success calls setData → dispatch → observer.onQueryUpdate → updateResult and framework notification. — [packages/query-core/src/queryObserver.ts#L110-L121](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/queryObserver.ts#L110-L121) [packages/query-core/src/queryObserver.ts#L459-L475](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/queryObserver.ts#L459-L475) [packages/query-core/src/query.ts#L725-L775](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/query.ts#L725-L775) [packages/query-core/src/query.ts#L892-L902](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/query.ts#L892-L902)
- Imperative fetch runs queryClient.query → defaultQueryOptions → QueryCache.build → isStaleByTime; stale entries fetch and fresh entries reuse state.data, with retries disabled unless explicitly configured and select applied afterward. — [packages/query-core/src/queryClient.ts#L580-L604](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/queryClient.ts#L580-L604) [packages/query-core/src/queryCache.ts#L159-L177](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/queryCache.ts#L159-L177) [packages/query-core/src/query.ts#L473-L487](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/query.ts#L473-L487)
- Comment submission runs Detail.submitForm → updateMovie.mutate → MutationObserver.mutate → Mutation.execute; useMovie.onMutate cancels detail fetches, snapshots old data, and writes optimistic data, with rollback onError and invalidation onSettled. — [examples/react/offline/src/App.tsx#L161-L177](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/examples/react/offline/src/App.tsx#L161-L177) [examples/react/offline/src/movies.ts#L22-L46](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/examples/react/offline/src/movies.ts#L22-L46) [packages/query-core/src/mutationObserver.ts#L207-L221](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/mutationObserver.ts#L207-L221) [packages/query-core/src/mutation.ts#L319-L346](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/mutation.ts#L319-L346)
- Mutation completion awaits global onSuccess → local onSuccess → global onSettled → local onSettled before success dispatch; restored pending mutations skip onMutate, and finally releases the retryer and advances the scope queue. — [packages/query-core/src/mutation.ts#L316-L383](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/mutation.ts#L316-L383) [packages/query-core/src/mutation.ts#L437-L444](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/mutation.ts#L437-L444) [packages/query-core/src/mutationCache.ts#L213-L224](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/mutationCache.ts#L213-L224)
- Persistent startup runs provider restore → persister.restoreClient → timestamp/maxAge/buster checks → hydrate → awaited onSuccess → isRestoring:false → cache subscriptions; later added/removed/updated events run save → dehydrate → persistClient. — [packages/react-query-persist-client/src/PersistQueryClientProvider.tsx#L33-L48](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/react-query-persist-client/src/PersistQueryClientProvider.tsx#L33-L48) [packages/query-persist-client-core/src/persist.ts#L71-L104](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-persist-client-core/src/persist.ts#L71-L104) [packages/query-persist-client-core/src/persist.ts#L113-L149](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-persist-client-core/src/persist.ts#L113-L149)

## Testing signals

Tests and CI were inspected, not executed; test existence and assertions are not passing results. The inspected suites use Vitest, fake timers, jsdom, React Testing Library, and type assertions. They exercise cache timing, observer transitions, mutation queues, hydration, restoration, and throttling. This inventory is bounded: the sampled tests do not establish production network, storage, browser, or every-adapter coverage.
- Core Vitest configuration searches src, disables watch, uses jsdom, enables typechecking and restored mocks, and enables Istanbul source coverage when CI is set. — [packages/query-core/vite.config.ts#L17-L30](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/vite.config.ts#L17-L30)
- query.test.tsx constructs a mounted client with fake timers and asserts longest-observed gcTime plus retry continuation after visibility restoration using simulated events. — [packages/query-core/src/__tests__/query.test.tsx#L21-L109](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/__tests__/query.test.tsx#L21-L109)
- The mutation scope test submits two mutations with the same scope, asserts the second is paused, and expects start-A/finish-A/start-B/finish-B ordering after advancing timers. — [packages/query-core/src/__tests__/mutation.test.tsx#L410-L468](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/__tests__/mutation.test.tsx#L410-L468)
- Hydration tests check Date serialization without mutating cached data, opt-out error redaction for a pending promise, and JSON round trips for multiple serializable data shapes. — [packages/query-core/src/__tests__/hydration.test.tsx#L43-L80](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/__tests__/hydration.test.tsx#L43-L80) [packages/query-core/src/__tests__/hydration.test.tsx#L84-L145](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/__tests__/hydration.test.tsx#L84-L145)
- React's successful-query test asserts the complete pending/fetching → success/idle result transition; its configuration uses a React plugin, jsdom, setup files, and three retries in CI. — [packages/react-query/src/__tests__/useQuery.test.tsx#L71-L155](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/react-query/src/__tests__/useQuery.test.tsx#L71-L155) [packages/react-query/vite.config.ts#L19-L34](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/react-query/vite.config.ts#L19-L34)
- PersistQueryClientProvider tests use an in-memory mock persister and assert idle fetching while restoring, hydrated data, and subsequent fetched data; this sampled test does not exercise real localStorage failures. — [packages/react-query-persist-client/src/__tests__/PersistQueryClientProvider.test.tsx#L17-L30](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/react-query-persist-client/src/__tests__/PersistQueryClientProvider.test.tsx#L17-L30) [packages/react-query-persist-client/src/__tests__/PersistQueryClientProvider.test.tsx#L61-L136](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/react-query-persist-client/src/__tests__/PersistQueryClientProvider.test.tsx#L61-L136)
- Type tests assert tagged-key inference using expectTypeOf, package scripts compile against TS 5.6–5.9, the catalog compiler, and TS 7.0, and asyncThrottle tests assert coalescing and interval timing. — [packages/query-core/src/__tests__/queryClient.test-d.tsx#L100-L107](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/__tests__/queryClient.test-d.tsx#L100-L107) [packages/query-core/package.json#L21-L30](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/package.json#L21-L30) [packages/query-async-storage-persister/src/__tests__/asyncThrottle.test.ts#L14-L74](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-async-storage-persister/src/__tests__/asyncThrottle.test.ts#L14-L74)
- PR CI starts distributed Nx agents and invokes test:pr; configured targets include lint, runtime/type/package checks and builds, while preview CI separately builds, publishes previews, and checks bundle size. No CI outcome was retrieved or executed. — [.github/workflows/pr.yml#L23-L40](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/.github/workflows/pr.yml#L23-L40) [.github/workflows/pr.yml#L54-L68](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/.github/workflows/pr.yml#L54-L68) [package.json#L15-L25](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/package.json#L15-L25)

## Risk map

These risks are source observations and explicitly labeled hypotheses, not confirmed vulnerabilities. The most consequential boundaries are request-local cache ownership, serialized data, incoming broadcast snapshots, and callback execution. Shared core behavior also has broad adapter impact and several compatibility branches. Release tooling performs privileged external actions and was inspected only as public source.
- SSR documentation explicitly warns that a module-level QueryClient shares cache across requests and can expose sensitive data; request-local client construction is an application integration requirement. — [docs/framework/react/guides/ssr.md#L51-L81](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/docs/framework/react/guides/ssr.md#L51-L81)
- Hypothesis: persisting sensitive successful query data could expose it through the chosen storage because the default adapter uses JSON serialization and a shared default key; dehydration filters and custom serializers are the available controls. (inferred) — [packages/query-async-storage-persister/src/index.ts#L42-L56](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-async-storage-persister/src/index.ts#L42-L56) [packages/query-core/src/hydration.ts#L178-L187](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/hydration.ts#L178-L187) [packages/query-core/src/hydration.ts#L224-L242](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/hydration.ts#L224-L242)
- Restoration checks timestamp age and buster, but hydrate consumes supplied arrays and states without structural schema validation in the inspected implementation; malformed deserialized state can throw and trigger cache removal. — [packages/query-persist-client-core/src/persist.ts#L79-L104](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-persist-client-core/src/persist.ts#L79-L104) [packages/query-core/src/hydration.ts#L265-L305](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/hydration.ts#L265-L305)
- Broadcast's incoming updated branch directly sets supplied state without comparing update timestamps; this differs from hydrate's newer-data checks and creates a freshness-review hotspot. — [packages/query-broadcast-client-experimental/src/index.ts#L148-L171](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-broadcast-client-experimental/src/index.ts#L148-L171) [packages/query-core/src/hydration.ts#L307-L338](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/hydration.ts#L307-L338)
- Cancellation depends on signal consumption: removing the last observer cancels and reverts when the signal was consumed or an initial load is paused; otherwise it cancels retries while allowing the current result to cache. — [packages/query-core/src/query.ts#L523-L543](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/query.ts#L523-L543) [packages/query-core/src/query.ts#L634-L645](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/query.ts#L634-L645) [packages/query-core/src/query.ts#L730-L737](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/query.ts#L730-L737)
- Mutation success/settled callback exceptions enter the mutation error path even after mutationFn resolves; exceptions from error callbacks are emitted as separate rejected promises, so transport success and reported mutation success can diverge. — [packages/query-core/src/mutation.ts#L346-L406](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/mutation.ts#L346-L406) [packages/query-core/src/mutation.ts#L409-L436](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/mutation.ts#L409-L436)
- Compatibility is active rather than dead code: deprecated imperative query methods remain, root ESLint restricts new calls, and createSyncStoragePersister is deprecated in favor of the async adapter. — [packages/query-core/src/queryClient.ts#L606-L652](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/queryClient.ts#L606-L652) [eslint.config.js#L47-L89](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/eslint.config.js#L47-L89) [packages/query-sync-storage-persister/src/index.ts#L41-L49](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-sync-storage-persister/src/index.ts#L41-L49)
- Release automation has write and OIDC permissions; create-github-release shells out to tag/push and gh release, writes notes outside the repository via tmpdir, and may delete newly created tags on failure. — [.github/workflows/release.yml#L20-L31](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/.github/workflows/release.yml#L20-L31) [scripts/create-github-release.mjs#L235-L275](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/scripts/create-github-release.mjs#L235-L275)

## Extension points

Extensions attach through options, callbacks, subscriptions, adapter primitives, and separate packages. Query and mutation functions are the main transport boundary, while persister contracts provide storage substitution. Manager setters allow environments and frameworks to replace event or scheduling behavior. Typed registration and ESLint rule tables supply compile-time and tooling extension mechanisms.
- Applications supply queryFn and mutationFn; query persisters wrap fetch execution, and QueryBehavior.onFetch can customize fetch context, with infinite queries selecting their built-in behavior. — [packages/query-core/src/query.ts#L649-L712](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/query.ts#L649-L712) [packages/query-core/src/mutation.ts#L295-L314](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/mutation.ts#L295-L314)
- setQueryDefaults and setMutationDefaults register options by hashed keys; matching query defaults merge in registration order, so specific defaults should follow generic ones. — [packages/query-core/src/queryClient.ts#L856-L888](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/queryClient.ts#L856-L888) [packages/query-core/src/queryClient.ts#L901-L916](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/queryClient.ts#L901-L916) [packages/query-core/src/queryClient.ts#L930-L945](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/queryClient.ts#L930-L945)
- Persister requires persistClient, restoreClient, and removeClient; the async storage factory accepts caller storage, key, throttle interval, serializers, and a retry callback that can transform or discard the snapshot. — [packages/query-persist-client-core/src/persist.ts#L12-L22](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-persist-client-core/src/persist.ts#L12-L22) [packages/query-async-storage-persister/src/index.ts#L17-L39](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-async-storage-persister/src/index.ts#L17-L39) [packages/query-async-storage-persister/src/index.ts#L63-L82](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-async-storage-persister/src/index.ts#L63-L82)
- Dehydration supports query/mutation selection, data serialization, and pending-error redaction; hydration accepts deserialization and restored query/mutation defaults. — [packages/query-core/src/hydration.ts#L42-L70](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/hydration.ts#L42-L70)
- focusManager.setEventListener and onlineManager.setEventListener replace environment listeners and clean up prior handlers; callers can also set focus or online state manually. — [packages/query-core/src/focusManager.ts#L77-L112](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/focusManager.ts#L77-L112) [packages/query-core/src/onlineManager.ts#L75-L103](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/onlineManager.ts#L75-L103)
- createNotifyManager exposes setNotifyFunction, setBatchNotifyFunction, and setScheduler to integrate test wrappers, framework batching, and alternate scheduling. — [packages/query-core/src/notifyManager.ts#L92-L135](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/notifyManager.ts#L92-L135)
- The Register interface supports declaration merging for defaultError, queryKey, mutationKey, queryMeta, and mutationMeta through core or adapter modules. — [packages/query-core/src/types.ts#L35-L85](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/types.ts#L35-L85)
- Framework APIs build on shared observers, with Lit exporting query/mutation controllers and Angular exporting injection/provider features; lint extensions register rule modules in rules.ts and configure presets in index.ts. — [packages/lit-query/src/index.ts#L18-L41](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/lit-query/src/index.ts#L18-L41) [packages/angular-query-experimental/src/index.ts#L25-L60](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/angular-query-experimental/src/index.ts#L25-L60) [packages/eslint-plugin-query/src/rules.ts#L20-L29](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/eslint-plugin-query/src/rules.ts#L20-L29) [packages/eslint-plugin-query/src/index.ts#L17-L30](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/eslint-plugin-query/src/index.ts#L17-L30)

## Contributor handoff

Tests and CI were inspected, not executed, and this source inventory is bounded rather than exhaustive. Future agents should begin with repository instructions, the owning package, and the relevant core-to-adapter flow. Core edits require attention to cache identity, observer timing, cancellation, mutation callbacks, and external snapshots. Validation commands below are recommendations for a future authorized implementation task, not actions performed during this investigation.
- AGENTS.md requires reading CONTRIBUTING.md before analysis or changes; contribution guidance requires focused changes, understood and verified generated code, and the repository PR template. — [AGENTS.md#L1-L9](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/AGENTS.md#L1-L9) [CONTRIBUTING.md#L15-L23](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/CONTRIBUTING.md#L15-L23)
- Resolve package-manager drift explicitly: CONTRIBUTING.md mentions pnpm v11, while the pinned root manifest specifies pnpm@12.4.2 and a matching minimum engine. — [CONTRIBUTING.md#L39-L49](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/CONTRIBUTING.md#L39-L49) [package.json#L8-L11](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/package.json#L8-L11)
- Read the runtime owner before adapter changes: useBaseQuery defaults options and owns React subscriptions, QueryObserver decides fetch/result behavior, and QueryClient owns caches and lifecycle listeners. — [packages/react-query/src/useBaseQuery.ts#L51-L116](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/react-query/src/useBaseQuery.ts#L51-L116) [packages/query-core/src/queryObserver.ts#L110-L165](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/queryObserver.ts#L110-L165) [packages/query-core/src/queryClient.ts#L89-L119](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/queryClient.ts#L89-L119)
- Preserve notification-aware writes: setQueryData applies an updater, skips undefined, and writes through Query.setData; direct state-object mutation bypasses QueryCache's documented notifications. — [packages/query-core/src/queryClient.ts#L298-L310](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/queryClient.ts#L298-L310) [packages/query-core/src/queryCache.ts#L106-L114](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/queryCache.ts#L106-L114)
- For authorized validation, run package runtime tests from the root through pnpm nx run @tanstack/{package-name}:test:lib; Nx compiles dependencies first, and package scripts provide separate type and package-export checks. — [CONTRIBUTING.md#L179-L217](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/CONTRIBUTING.md#L179-L217) [nx.json#L60-L85](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/nx.json#L60-L85) [packages/query-core/package.json#L21-L31](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/package.json#L21-L31)
- Published-package changes require a changeset, while docs, CI, examples, and development-only changes do not; Changesets config places many packages in fixed version groups. — [CONTRIBUTING.md#L165-L167](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/CONTRIBUTING.md#L165-L167) [.changeset/config.json#L11-L39](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/.changeset/config.json#L11-L39)
- Reference markdown is generated from source JSDoc, so edit JSDoc rather than generated pages; new documentation pages also require updating docs/config.json. — [CONTRIBUTING.md#L124-L133](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/CONTRIBUTING.md#L124-L133)
- Do not assume snapshots preserve executable behavior: dehydrateMutation stores key/state/scope/meta, and the offline example registers a default mutationFn specifically to resume paused mutations after reload. — [packages/query-core/src/hydration.ts#L102-L108](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/hydration.ts#L102-L108) [examples/react/offline/src/App.tsx#L49-L55](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/examples/react/offline/src/App.tsx#L49-L55) [packages/query-core/src/mutation.ts#L295-L301](https://github.com/TanStack/query/blob/29859ae60c8dca0a5cdbf8abccc775b655cf43e2/packages/query-core/src/mutation.ts#L295-L301)

Source repository: https://github.com/TanStack/query
Full evidence corpus: https://github.com/Codevetter/codevetter/tree/main/benchmarks/repo-unpacks/query.json

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
