Cache management
Operations on the cache itself — invalidation, refetch, optimistic writes, lifecycle.
Invalidation
queryAtom.invalidate({ queryKey, exact?: boolean }): Promise<void>queryAtom.invalidateAll(): Promise<void>queryAtom.invalidateBackground({ queryKey }): void // requestIdleCallbackqueryAtom.invalidateBackgroundAll(): voidMatching is segment-aware. invalidate({ queryKey: ["users", 1] }) matches:
["users", 1]✓ (exact)["users", 1, "profile"]✓ (child)
But NOT:
["users", 10]✗["users", 100]✗
Internally: queries are hashed via canonical JSON; prefix matching requires a , boundary after the parent’s last element, so ["users",1] and ["users",10] differ at position 9.
exact: true only refetches the literal hash match.
Refetch
queryAtom.refetchQuery(queryKey): Promise<void> // throws if missingqueryAtom.refetchMultipleQueries(queryKey[]): Promise<void>queryAtom.refetchQueryBackground(queryKey): voidqueryAtom.refetchMultipleQueriesBackground(queryKey[]): voidRefetches share the in-flight dedup map — calling refetchQuery(key) while a fetch is already running for that key joins the existing promise.
Optimistic writes
queryAtom.updateQueryData<T>(queryKey, (old: T | undefined) => T): voidReplaces the cached value without triggering a refetch. Subscribers re-render. Use inside onMutate for optimistic patterns; pair with invalidate in onSettled to re-sync.
Seeding
queryAtom.seedQuery<T>({ queryKey, data, freshFor?: number }): voidInserts a state: "success" entry into the cache. Consumers see it on first read, no refetch unless stale per freshFor / staleTime. The React wrapper is <HydrateQueries>.
Direct reads
queryAtom.getQuery(queryKey): Query | undefinedqueryAtom.getData(queryKey): unknownqueryAtom.isStale(queryKey, staleTime?): booleanDestruction
queryAtom.destroyQuery(queryKey): voidRemoves the entry from the cache AND aborts any in-flight fetch for that key. Idempotent — no-op for unknown keys.
queryAtom.clearCache(): voidWipes everything and aborts every in-flight fetch.
Stats and GC
queryAtom.getCacheStats(): { totalQueries: number; loadingQueries: number; errorQueries: number; successfulQueries: number; totalDataSize: number;}
queryAtom.garbageCollect(gcTime?: number): number // returns count removedqueryAtom.limitCacheSize(maxQueries?: number): number
queryAtom.setupAutoGC( interval?: number, // default 60_000 ms gcTime?: number, // default 5 * 60_000 ms maxQueries?: number, // default 100): () => void // returns stop functionsetupAutoGC is called automatically on the first useQuery so consumers don’t need to remember it. The default cadence is “every minute, evict anything unobserved for more than 5 minutes.”
GC respects observer counts. A query with mounted consumers is never GC’d, even if its data is old. Only queries with zero observers (since gcTime ms ago) get evicted.
Subscribing without a hook
queryAtom.onQueryChange( queryKey, (next: Query | undefined, prev: Query | undefined) => void,): EventSubscriptionFires on every slice change for the named key — including create (prev === undefined) and destroy (next === undefined). Returns { unsubscribe }.