Important Defaults
Key points (written by a model)
- By default, useQuery and useInfiniteQuery queries consider cached data stale, so stale queries refetch automatically on mount, window focus, and network reconnect.
- A query with staleTime set is fresh until that time elapses; Infinity allows manual invalidation refetch, while static never refetches even when invalidated.
- Inactive queries are garbage collected after 5 minutes by default, controlled by the gcTime option.
- Failed queries are silently retried 3 times with exponential backoff before the error is captured and displayed.
- Query results are structurally shared by default so unchanged data keeps the same reference, though this works only with JSON-compatible values.
Model-written
contextclaimmethodsetupresultanalysislimitation
Out of the box, TanStack Query is configured with aggressive but sane defaults. Sometimes these defaults can catch new users off guard or make learning/debugging difficult if they are unknown by the user. Keep them in mind as you continue to learn and use TanStack Query:Out of the box, TanStack Query is configured with aggressive but sane defaults. Sometimes these defaults can catch new users off guard or make learning/debugging difficult if they are unknown by the user.TanStack Query is configured with aggressive but sane defaults Unknown defaults can catch new users off guard or make learning and debugging difficult, so keep them in mindTanStack Query is configured with aggressive but sane defaultsaggressive but sane
- Query instances via
useQueryoruseInfiniteQueryby default consider cached data as stale.Query instances viauseQueryoruseInfiniteQueryby default consider cached data as stale.useQuery and useInfiniteQuery treat cached data as stale by default Staleness drives background refetching whenever the query mounts, refocuses or reconnectsuseQuery and useInfiniteQuery treat cached data as stale by defaultcached data
To change this behavior, you can configure your queries both globally and per-query using the
staleTimeoption. Specifying a longerstaleTimemeans queries will not refetch their data as oftenTo change this behavior, you can configure your queries both globally and per-query using thestaleTimeoption. Specifying a longerstaleTimemeans queries will not refetch their data as oftenSet staleTime globally or per-query to change staleness behavior A longer staleTime means queries refetch their data less oftenSet staleTime globally or per-query to change staleness behaviorstaleTime
- A Query that has a
staleTimeset is considered fresh until thatstaleTimehas elapsed.A Query that has astaleTimeset is considered fresh until thatstaleTimehas elapsed.A query with staleTime set stays fresh until it elapses After staleTime passes, the query becomes stale and normal background refetching resumesA query with staleTime set stays fresh until it elapsesstaleTime set- set
staleTimeto e.g.2 * 60 * 1000to make sure data is read from the cache, without triggering any kinds of refetches, for 2 minutes, or until the Query is invalidated manually.setstaleTimeto e.g.2 60 1000to make sure data is read from the cache, without triggering any kinds of refetches, for 2 minutes, or until the Query is invalidated manually.staleTime of 2 minutes reads cache without refetches until invalidated Manual invalidation still overrides the fresh window and triggers a refetchstaleTime of 2 minutes reads cache without refetches until invalidatedstaleTime of 2 minutes - set
staleTimetoInfinityto never trigger a refetch until the Query is invalidated manually.staleTime Infinity never refetches until manual invalidation Manual invalidation remains the only path to refresh the query datastaleTime Infinity never refetches until manual invalidationstaleTime Infinity - set
staleTimeto'static'to never trigger a refetch, even if the Query is invalidated manually.staleTime static never refetches, even after manual invalidation No invalidation path can force a refetch once static is setstaleTime static never refetches, even after manual invalidationstaleTime static
'static'andInfinityboth prevent staleness-based refetches, but'static'is stricter:queryClient.invalidateQueries()can invalidate a query withstaleTime: Infinity, but has no effect onstaleTime: 'static'.refetchOnMount,refetchOnWindowFocus, andrefetchOnReconnectset to"always"are also blocked by'static'. Use'static'for data that cannot change while the app is running: feature flags fetched at boot, user permissions loaded at login, static reference tables. UseInfinitywhen you still want manual invalidation to work.'static'andInfinityboth prevent staleness-based refetches, but'static'is stricter:queryClient.invalidateQueries()can invalidate a query withstaleTime: Infinity, but has no effect onstaleTime: 'static'. Use'static'for data that cannot change while the app is running: feature flags fetched at boot, user permissions loaded at login, static reference tables. UseInfinitywhen you still want manual invalidation to work.static is stricter than Infinity, blocking invalidation too Use static for data that cannot change while the app runs, Infinity when manual invalidation is still neededstatic is stricter than Infinity, blocking invalidation toostatic
- Stale queries are refetched automatically in the background when:Stale queries are refetched automatically in the background when:Stale queries refetch automatically in the background Three trigger points follow: query mount, window refocus and network reconnectStale queries refetch automatically in the backgroundStale queries
- New instances of the query mountNew instances of the query mountNew query instances mounting triggers a refetchNew query instances mounting triggers a refetchNew instances
- The window is refocusedThe window is refocusedRefocusing the window triggers a refetchRefocusing the window triggers a refetchwindow refocus
- The network is reconnectedThe network is reconnectedReconnecting the network triggers a refetchReconnecting the network triggers a refetchnetwork reconnect
Setting
staleTimeis the recommended way to avoid excessive refetches, but you can also customize the points in time for refetches by setting options likerefetchOnMount,refetchOnWindowFocusandrefetchOnReconnect.SettingstaleTimeis the recommended way to avoid excessive refetches, but you can also customize the points in time for refetches by setting options likerefetchOnMount,refetchOnWindowFocusandrefetchOnReconnect.staleTime is the recommended way to avoid excessive refetches Refetch points can also be customized with refetchOnMount, refetchOnWindowFocus and refetchOnReconnectstaleTime is the recommended way to avoid excessive refetchesstaleTime
Queries can optionally be configured with a
refetchIntervalto trigger refetches periodically, which is independent of thestaleTimesetting. See Polling for details.Queries can optionally be configured with arefetchIntervalto trigger refetches periodically, which is independent of thestaleTimesetting.refetchInterval triggers periodic refetches independent of staleTime Polling behavior is unaffected by the staleness settingrefetchInterval triggers periodic refetches independent of staleTimerefetchIntervalQuery results that have no more active instances of
useQuery,useInfiniteQueryor query observers are labeled as "inactive" and remain in the cache in case they are used again at a later time.Query results that have no more active instances ofuseQuery,useInfiniteQueryor query observers are labeled as "inactive" and remain in the cache in case they are used again at a later time.Queries with no active instances become inactive and stay cached They remain available in case they are used again laterQueries with no active instances become inactive and stay cachedactive instancesBy default, "inactive" queries are garbage collected after 5 minutes.
By default, "inactive" queries are garbage collected after 5 minutes.Inactive queries are garbage collected after 5 minutes by default The cache window gives later usage a chance to reuse the data before removalInactive queries are garbage collected after 5 minutes by defaultInactive queriesTo change this, you can alter the default
gcTimefor queries to something other than1000 * 60 * 5milliseconds.Queries that fail are silently retried 3 times, with exponential backoff delay before capturing and displaying an error to the UI.
Queries that fail are silently retried 3 times, with exponential backoff delay before capturing and displaying an error to the UI.Failed queries are silently retried 3 times with exponential backoff The error reaches the UI only after all retries are exhaustedFailed queries are silently retried 3 times with exponential backoffsilently retried 3 timesTo change this, you can alter the default
retryandretryDelayoptions for queries to something other than3and the default exponential backoff function.
- Query results by default are structurally shared to detect if data has actually changed and if not, the data reference remains unchanged to better help with value stabilization with regards to useMemo and useCallback. If this concept sounds foreign, then don't worry about it! 99.9% of the time you will not need to disable this and it makes your app more performant at zero cost to you.Query results by default are structurally shared to detect if data has actually changed and if not, the data reference remains unchanged to better help with value stabilization with regards to useMemo and useCallback. 99.9% of the time you will not need to disable this and it makes your app more performant at zero cost to you.Structural sharing keeps unchanged data references stable by default Stable references help useMemo and useCallback, and nearly no one needs to disable itStructural sharing keeps unchanged data references stable by defaultStructural sharing
Structural sharing only works with JSON-compatible values, any other value types will always be considered as changed. If you are seeing performance issues because of large responses for example, you can disable this feature with the
config.structuralSharingflag. If you are dealing with non-JSON compatible values in your query responses and still want to detect if data has changed or not, you can provide your own custom function asconfig.structuralSharingto compute a value from the old and new responses, retaining references as required.Structural sharing only works with JSON-compatible values, any other value types will always be considered as changed. If you are seeing performance issues because of large responses for example, you can disable this feature with theconfig.structuralSharingflag. If you are dealing with non-JSON compatible values in your query responses and still want to detect if data has changed or not, you can provide your own custom function asconfig.structuralSharingto compute a value from the old and new responses, retaining references as required.Structural sharing only works with JSON-compatible values Other types always count as changed; disable it or supply a custom function if neededStructural sharing only works with JSON-compatible valuesJSON-compatible values
Further Reading
Community articles explaining TanStack Query defaults further
Have a look at the following articles from our Community Resources for further explanations of the defaults:Have a look at the following articles from our Community Resources for further explanations of the defaults:Community articles explain the defaults further They are recommended reading for deeper understanding of the defaultsCommunity articles explain the defaults furtherCommunity articles