Skip to content
advanced Phase 11 · HTTP Clients and Data Fetching

Client-Side Caching with TanStack Query

De-duplicate requests, cache by key, and invalidate after mutations.

45m
0 problems
Topic Progress 0%

Client-Side Caching with TanStack Query: Core Concepts

Cache server state by query identity

TanStack Query for Vue manages asynchronous server state: query caching, request deduplication, background refetch, retries, and mutation-driven invalidation. A query key identifies the data. Keys should be stable arrays that include every variable affecting the response, such as resource id, filter, page, and tenant. If the key omits a filter, the cache can return one query's data for another view.

The query function performs the request and should reject for non-success HTTP responses so the library can represent an error. Vue Query exposes data, pending/loading, error, and fetching state through its composable API. The exact flags and API names vary by library version; follow the installed version's documentation. Keep query functions independent of component presentation.

Freshness is different from retention

Stale time controls how long data is considered fresh and can avoid refetch on mount or focus. Garbage-collection time controls how long an inactive query remains in memory. Freshness is a product decision: rapidly changing inventory needs a shorter stale window than a static reference list. A long stale time improves responsiveness but can display old data; a short time increases network load.

Stale-while-revalidate can show cached data immediately and fetch a newer value in the background. Expose background fetching distinctly from initial loading so the view does not replace usable content with a full-screen spinner every time. If the query fails while cached data exists, decide whether to retain the old value with a warning or replace it with an error screen.

Coordinate mutation and invalidation

After a mutation, invalidate related query keys so affected views refetch. Invalidate narrowly enough to avoid refreshing the entire application, but broadly enough that stale dependent data is not left behind. For a simple optimistic update, snapshot prior cache data, apply the expected change, roll back on error, and invalidate or reconcile with the server response on success. Optimism is harder when updates are non-commutative or multiple mutations overlap.

Query cache is not an authorization mechanism. Server APIs must authorize every request, and cache keys should include user or tenant scope when responses differ. Clear or remove user-scoped cached queries on logout or identity switch. Do not persist sensitive query data unless the storage and encryption model is explicitly designed for it.

SSR and hydration

SSR query prefetching requires a request-scoped QueryClient and careful dehydration/hydration. A module-global client on the server can leak cached data across requests. Dehydrate only data safe for the rendered user and ensure the client uses matching keys to avoid duplicate fetches. Configure server and browser freshness so hydration does not immediately refetch unnecessarily or preserve stale data too long.

Use one clear owner for server data. Storing the same response independently in Pinia and Query cache creates synchronization work. Pinia can own client workflow state while Query manages remote data and cache lifecycle. Decide which system is authoritative and how mutations update it.

Query caching is useful when multiple views share server data or need robust freshness behavior. For a one-off request with no sharing or caching need, explicit component state or a small composable may be simpler. Choose key, freshness, invalidation, retry, and logout policy intentionally.

Client-Side Caching with TanStack Query: Practice

Define a complete query key

For a project list filtered by status and page, use a stable key such as ['projects', tenantId, status, page]. Include every value used by the query function that changes the result. Do not put a freshly allocated object in the key without ensuring its structure is stable. Query keys are cache identity and invalidation boundaries, not decorative labels.

Implement a query function that checks response.ok and throws a typed error for non-success status. Configure a stale time based on how quickly project status changes. Keep data visible during a background refetch and expose fetching state with a subtle indicator. When the user changes the page or filter, the key changes and the correct cache entry is selected.

Update after a mutation

After renaming a project, update the detail query from the server response and invalidate the list query. If an optimistic update is worthwhile, cancel in-flight list queries, snapshot prior data, patch the cache, and restore the snapshot on error. On success, use the server's canonical result and invalidate any related aggregates. Avoid optimistic updates when ordering, uniqueness, or server-generated fields make the result hard to predict.

If two mutations overlap, a simple snapshot rollback can erase a newer successful change. Serialize operations, use versioning, or reconcile with a refetch. Test the failure sequence deliberately. Query invalidation should be specific; invalidating every query after every action creates unnecessary network load and can make the app feel unstable.

Manage identity and freshness

Include tenant or user scope in query keys when returned data differs. On logout or identity switch, clear private queries so the next user cannot see stale content. Avoid persisting sensitive query cache by default. If offline persistence is required, review encryption, expiry, logout purge, and schema migration.

Set stale and garbage-collection policies separately. A query can be stale while still cached; stale data may render immediately while a background refresh runs. An inactive query can remain in memory for a period to speed navigation. Tune those values with data-change frequency and memory constraints. Window-focus refetch is useful for collaborative or time-sensitive data, but may create traffic spikes across many tabs.

Test cache behavior

Use a fresh QueryClient per test and disable retries unless a retry is the behavior under test. Verify identical keys deduplicate requests, distinct keys do not share results, invalidation triggers the intended refetch, and stale data is handled on error. Test SSR with a separate client per request. Confirm hydration reuses matching data and does not expose data from another identity.

Finally, inspect how Pinia and Query are used together. Keep remote query results in Query cache unless the app has a clear reason to copy them into a store. Keep UI workflow state in Pinia where shared. One owner per state category reduces stale copies and synchronization bugs.

Mutations should invalidate the smallest related key set that restores consistency. If a project rename affects a detail page, filtered lists, and a dashboard count, define those dependencies explicitly. Over-invalidation creates unnecessary requests; under-invalidation leaves stale views. Centralize key factories so query and mutation code use the same structure.

Client-Side Caching with TanStack Query: Trade-offs and Interviews

Cache keys are correctness boundaries

An incomplete query key can return data for the wrong filter, tenant, or user. Include every request input and identity scope that changes the response. Use stable values and centralize key construction when multiple components query the same resource. Invalidate related keys after mutations with a deliberate dependency map.

Freshness trades network load for staleness. A longer stale time avoids refetch but can show outdated server state; a shorter one increases requests and may cause UI churn. Keep cached data visible during background fetch when it remains safe. If a query fails, decide whether stale data is useful or misleading for that view.

Optimism and invalidation have costs

Optimistic updates make interactions feel fast but require rollback and conflict handling. They can be unsafe for money, permissions, or non-commutative operations. A server response followed by targeted invalidation is simpler when latency is acceptable. Do not invalidate everything; broad invalidation can create load spikes and inconsistent loading states.

SSR requires request-scoped QueryClients and safe dehydration. A shared server cache can leak user data. Clear private queries on identity changes and avoid persisting sensitive data without a reviewed storage design. Keep Query cache and Pinia state roles distinct to prevent duplicate sources of truth.

In an interview, explain query keys, stale time versus garbage collection, mutation invalidation, and one optimistic update with rollback. Discuss user scoping and SSR isolation. Then say when a custom composable is simpler. This demonstrates cache design as data correctness and lifecycle management, not merely a performance trick.

Hydration should use the same query-key factory and data schema on server and client. If a server query includes tenant identity but the browser key omits it, the cache can collide. Do not dehydrate credentials or sensitive server-only fields. Set freshness so data is reused when valid and refetched when the server/client timing makes it stale.

Cache invalidation is a correctness operation. A mutation can affect queries not obvious from the component that triggered it. Use domain-level key groups and test the expected invalidations. For optimistic changes, cancellation, snapshot, update, rollback, and reconciliation must occur in a defined order. If a mutation fails after another mutation succeeds, naive snapshot rollback can erase the newer state.

Retries and focus refetching can create traffic bursts when many tabs or clients return at once. Use bounded retry policies and consider jitter or a server rate limit. Configure refetch behavior according to data freshness and user impact, not library defaults alone. Monitor request volume, cache hit rate, and stale-data complaints after rollout.

In an interview, distinguish server-state cache from client-owned Pinia state. Explain key completeness, stale time, invalidation after mutation, and logout clearing. Describe one optimistic update rollback case and one SSR isolation risk. This connects cache performance to consistency, identity, and lifecycle.

Document who owns each invalidation rule and review it whenever a mutation changes resource relationships.

Treat query keys as part of the data contract. Include every variable that changes the response, such as account ID, filters, locale, or page cursor; omit a variable and the cache can return another request's data. Keys should be stable serializable values, not freshly created opaque objects with hidden identity. On logout or account switch, remove or isolate user-scoped cache entries so one session cannot briefly display another user's result. Mutation invalidation should target the smallest set of affected queries that remains correct. If optimistic updates are used, snapshot prior data and roll back on failure, then reconcile with the server response rather than assuming the write succeeded.

Quiz

1. Which statement about Client-Side Caching with TanStack Query is accurate?

Question 1 options

2. When reviewing Client-Side Caching with TanStack Query, which point must hold?

Question 2 options

3. What belongs in a query key?

Question 3 options

4. What is the difference between stale time and garbage-collection time?

Question 4 options

Flashcards

Question

What is Client-Side Caching with TanStack Query?

Answer

De-duplicate requests, cache by key, and invalidate after mutations.

Question

Client-Side Caching with TanStack Query: why it matters

Answer

Query keys identify cached data so repeated components share one network request.

Question

Client-Side Caching with TanStack Query: key detail

Answer

Stale-while-revalidate shows cached data instantly and refreshes it in the background.

Question

Client-Side Caching with TanStack Query: practical note

Answer

Mutation onSuccess invalidates related keys to refetch affected lists automatically.

Question

What belongs in a query key?

Answer

Query keys define cache identity; omitting a request input can return the wrong cached result.

Revision Notes

Key Takeaways

  • 1. Query keys identify cached data so repeated components share one network request.
  • 2. Stale-while-revalidate shows cached data instantly and refreshes it in the background.
  • 3. Mutation onSuccess invalidates related keys to refetch affected lists automatically.

Interview Tips

  • • Explain Client-Side Caching with TanStack Query with one concrete example from real vue work, not a textbook restatement.
  • • Discuss the trade-off: when Client-Side Caching with TanStack Query helps and when a lighter approach wins.
  • • Place Client-Side Caching with TanStack Query inside the HTTP Clients and Data Fetching phase — interviewers check that you see the progression, not isolated facts.

Cheat Sheet

Client-Side Caching with TanStack Query Cheat Sheet

Phase: HTTP Clients and Data Fetching | Level: advanced

Key points:

  • Query keys identify cached data so repeated components share one network request.
  • Stale-while-revalidate shows cached data instantly and refreshes it in the background.
  • Mutation onSuccess invalidates related keys to refetch affected lists automatically.
  • Window focus refetching keeps data fresh when the user returns to the tab.

Tags: vue, caching, http

Continue Learning

Before You Start

  • No prerequisites listed.

Related Reading