Skip to main content

Important Defaults

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 useQuery or useInfiniteQuery by default consider cached data as stale.
    Query instances via useQuery or useInfiniteQuery by 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 reconnects
    useQuery and useInfiniteQuery treat cached data as stale by default
    cached data

To change this behavior, you can configure your queries both globally and per-query using the staleTime option. Specifying a longer staleTime means queries will not refetch their data as often

To change this behavior, you can configure your queries both globally and per-query using the staleTime option. Specifying a longer staleTime means queries will not refetch their data as often
Set staleTime globally or per-query to change staleness behavior A longer staleTime means queries refetch their data less often
Set staleTime globally or per-query to change staleness behavior
staleTime
  • A Query that has a staleTime set is considered fresh until that staleTime has elapsed.
    A Query that has a staleTime set is considered fresh until that staleTime has elapsed.
    A query with staleTime set stays fresh until it elapses After staleTime passes, the query becomes stale and normal background refetching resumes
    A query with staleTime set stays fresh until it elapses
    staleTime set
    • set staleTime to e.g. 2 * 60 * 1000 to make sure data is read from the cache, without triggering any kinds of refetches, for 2 minutes, or until the Query is invalidated manually.
      set staleTime to e.g. 2 60 1000 to 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 refetch
      staleTime of 2 minutes reads cache without refetches until invalidated
      staleTime of 2 minutes
    • set staleTime to Infinity to never trigger a refetch until the Query is invalidated manually.
      set staleTime to Infinity to 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 data
      staleTime Infinity never refetches until manual invalidation
      staleTime Infinity
    • set staleTime to 'static' to never trigger a refetch, even if the Query is invalidated manually.
      set staleTime to '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 set
      staleTime static never refetches, even after manual invalidation
      staleTime static

'static' and Infinity both prevent staleness-based refetches, but 'static' is stricter: queryClient.invalidateQueries() can invalidate a query with staleTime: Infinity, but has no effect on staleTime: 'static'. refetchOnMount, refetchOnWindowFocus, and refetchOnReconnect set 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. Use Infinity when you still want manual invalidation to work.

'static' and Infinity both prevent staleness-based refetches, but 'static' is stricter: queryClient.invalidateQueries() can invalidate a query with staleTime: Infinity, but has no effect on staleTime: '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. Use Infinity when 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 needed
static is stricter than Infinity, blocking invalidation too
static
  • 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 reconnect
    Stale queries refetch automatically in the background
    Stale queries
    • New instances of the query mount
      New instances of the query mount
      New query instances mounting triggers a refetch
      New query instances mounting triggers a refetch
      New instances
    • The window is refocused
      The window is refocused
      Refocusing the window triggers a refetch
      Refocusing the window triggers a refetch
      window refocus
    • The network is reconnected
      The network is reconnected
      Reconnecting the network triggers a refetch
      Reconnecting the network triggers a refetch
      network reconnect

Setting staleTime is the recommended way to avoid excessive refetches, but you can also customize the points in time for refetches by setting options like refetchOnMount, refetchOnWindowFocus and refetchOnReconnect.

Setting staleTime is the recommended way to avoid excessive refetches, but you can also customize the points in time for refetches by setting options like refetchOnMount, refetchOnWindowFocus and refetchOnReconnect.
staleTime is the recommended way to avoid excessive refetches Refetch points can also be customized with refetchOnMount, refetchOnWindowFocus and refetchOnReconnect
staleTime is the recommended way to avoid excessive refetches
staleTime
  • Queries can optionally be configured with a refetchInterval to trigger refetches periodically, which is independent of the staleTime setting. See Polling for details.

    Queries can optionally be configured with a refetchInterval to trigger refetches periodically, which is independent of the staleTime setting.
    refetchInterval triggers periodic refetches independent of staleTime Polling behavior is unaffected by the staleness setting
    refetchInterval triggers periodic refetches independent of staleTime
    refetchInterval
  • Query results that have no more active instances of useQuery, useInfiniteQuery or 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 of useQuery, useInfiniteQuery or 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 later
    Queries with no active instances become inactive and stay cached
    active instances
  • By 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 removal
    Inactive queries are garbage collected after 5 minutes by default
    Inactive queries

    To change this, you can alter the default gcTime for queries to something other than 1000 * 60 * 5 milliseconds.

  • 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 exhausted
    Failed queries are silently retried 3 times with exponential backoff
    silently retried 3 times

    To change this, you can alter the default retry and retryDelay options for queries to something other than 3 and 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 it
    Structural sharing keeps unchanged data references stable by default
    Structural 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.structuralSharing flag. 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 as config.structuralSharing to 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 the config.structuralSharing flag. 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 as config.structuralSharing to 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 needed
Structural sharing only works with JSON-compatible values
JSON-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