Core Cache and Observers Reference
Purpose and Scope
TanStack Query is described in the official product docs as a server-state manager: async data receives a cache, a lifecycle, and declarative APIs for fetching, sharing, refetching, mutating, and observing state across TypeScript applications. This reference explains that core model from the perspective of the repository documentation available for this page. The key idea is that framework adapters do not invent their own cache semantics; they provide framework-native entry points that connect application code to a QueryClient, query observers, background fetching state, hydration choices, and development inspection tools.
Sources: docs/framework/angular/reference/functions/provideTanStackQuery.md, docs/framework/angular/guides/background-fetching-indicators.md
Because the supplied source files are Angular-facing docs, this page treats Angular Query as the visible adapter over the core rather than as a separate state-management system. provideTanStackQuery wires a QueryClient into Angular dependency injection, injectQuery observes one cached query from a component, and injectIsFetching observes aggregate fetching activity. These names are Angular-specific, but the concepts they surface are the same ones used by other adapters: cache identity comes from query keys, execution is delegated to promise-returning query functions, and UI updates are driven by observer state rather than manual synchronization.
Sources: docs/framework/angular/reference/functions/provideTanStackQuery.md, docs/framework/angular/angular-httpclient-and-other-data-fetching-clients.md, docs/framework/angular/guides/background-fetching-indicators.md
Relevant Source Files
docs/framework/angular/reference/functions/provideTanStackQuery.mddocuments the provider-level entry point that installs aQueryClientand optional features for Angular applications.docs/framework/angular/angular-httpclient-and-other-data-fetching-clients.mdexplains that TanStack Query fetching is promise-based and backend-client agnostic, including AngularHttpClient,fetch, and specialized clients such asgraphql-request.docs/framework/angular/guides/background-fetching-indicators.mdshows observer-facing state such asisPending,isError,isSuccess,isFetching,data, anderror, plus the aggregateinjectIsFetchingsignal.docs/framework/angular/devtools.mddocuments the devtools feature and itswithDevtoolsintegration, which makes query and mutation cache state inspectable during development or controlled production scenarios.docs/config.jsonmaps the documentation site structure and shows that Angular sits beside React, Solid, Vue, Svelte, and Lit as a framework section, supporting the adapter-over-core reading of the API.docs/community-resources.mdlists ecosystem learning and utility resources, including tools for standardized query keys and generated clients that affect how teams model cache identity around the core.
System-to-Code Mapping
At the center of the system is QueryClient. In the Angular reference, provideTanStackQuery(queryClient, ...features): Provider[] accepts either a QueryClient instance or an Angular InjectionToken<QueryClient>, then returns providers that enable TanStack Query functionality for the application. This is the adapter boundary: Angular dependency injection owns how the client is supplied, while the client owns query caching, mutation coordination, default options, and the shared lifecycle that components observe. Optional features, such as devtools, are attached at the same provider boundary so application setup remains explicit.
Sources: docs/framework/angular/reference/functions/provideTanStackQuery.md, docs/framework/angular/devtools.md
The cache is observed through framework-native APIs. The Angular background-fetching guide shows a component with todosQuery = injectQuery(() => ({ queryKey: ['todos'], queryFn: fetchTodos })). The template reads todosQuery.isPending(), todosQuery.isError(), todosQuery.isSuccess(), todosQuery.isFetching(), todosQuery.data(), and todosQuery.error(). Those accessors are the practical observer contract: application rendering reacts to derived query state, while the cache coordinates whether data is loading, successful, erroneous, or refreshing in the background.
Sources: docs/framework/angular/guides/background-fetching-indicators.md
The manager and notification layers are not named directly in the supplied Angular docs, but their effects are visible in the public API shape. A component can distinguish initial pending state from background fetching, and a separate global component can call injectIsFetching() to show application-wide network activity. That only works if cache changes are collected and exposed consistently to all observers. In day-to-day use, the important contract is not a manual event bus; it is a set of stable signals or hook results that notify consumers when the relevant query or aggregate fetching state changes.
Sources: docs/framework/angular/guides/background-fetching-indicators.md
API Components
| Component | Public shape in supplied docs | Core role |
|---|---|---|
QueryClient | Constructed with new QueryClient() and passed to provideTanStackQuery | Owns the shared query and mutation cache for an app boundary |
provideTanStackQuery | function provideTanStackQuery(queryClient, ...features): Provider[] | Installs the client and optional features into Angular DI |
InjectionToken<QueryClient> | Accepted instead of a direct QueryClient instance | Allows lazy-loaded routes or components to share or defer the client |
injectQuery | Takes options with queryKey and queryFn | Creates an observer for one cached query and exposes state accessors |
injectIsFetching | Returns aggregate fetching state | Observes cache-wide background fetching activity |
withDevtools | Optional feature passed to provideTanStackQuery | Enables cache and mutation inspection tooling |
Promise-returning queryFn | May use fetch, graphql-request, or converted Angular HttpClient observables | Supplies the asynchronous work that populates cache entries |
provideTanStackQuery is the most explicit reference signature in the supplied sources. It returns Angular Provider[], so it belongs in application configuration, standalone bootstrap providers, NgModule providers, or lazy-loaded provider arrays. The docs show a direct new QueryClient() setup for most applications and an InjectionToken pattern as an advanced optimization for lazy-loaded routes. The optimization is framed as small: most applications should provide the client in the main application config, while lazy-loading can reduce the main bundle when TanStack Query is only needed in selected routes.
Sources: docs/framework/angular/reference/functions/provideTanStackQuery.md
withDevtools is a feature attached to the same provider call. In normal Angular usage, importing it from @tanstack/angular-query-experimental/devtools makes devtools load automatically only in development mode when loadDevtools is unset or set to 'auto'. The production subpath, @tanstack/angular-query-experimental/devtools/production, exposes the same function for controlled production loading. The option callback supports reactivity through signals, which means teams can derive devtools loading from environment configuration or a runtime toggle without changing the core client setup.
Sources: docs/framework/angular/devtools.md
Execution Flow
A typical execution flow starts when the application config provides the client. Angular then makes that client available to components and features through dependency injection. A component calls injectQuery with a query key and query function. The query key identifies the cache entry, and the query function returns a promise for the data. If the data is not already usable for the configured lifecycle, TanStack Query executes the promise and records the resulting state. The component does not subscribe to the network call directly; it reads observer state exposed by the adapter.
Sources: docs/framework/angular/reference/functions/provideTanStackQuery.md, docs/framework/angular/guides/background-fetching-indicators.md
The Angular HttpClient guide is important because it draws a clean boundary around query functions. TanStack Query is promise based and can use any asynchronous client, including browser fetch, graphql-request, and Angular HttpClient. Since Angular HttpClient returns observables today, the docs convert them with lastValueFrom or firstValueFrom before returning from queryFn. This preserves the core contract: Query does not need to know which transport produced the data, only that the query function resolves or rejects through a promise.
Sources: docs/framework/angular/angular-httpclient-and-other-data-fetching-clients.md
@Component({
// ...
})
class ExampleComponent {
private readonly http = inject(HttpClient)
readonly query = injectQuery(() => ({
queryKey: ['repoData'],
queryFn: () =>
lastValueFrom(
this.http.get('https://api.github.com/repos/tanstack/query'),
),
}))
}Once the query is running or cached, observers drive user interface behavior. The guide distinguishes initial loading from background refresh: isPending() can show a first-load message, while isFetching() can show a smaller refreshing indicator after successful data already exists. A global loading component can use injectIsFetching() to report that any query is fetching in the background. This separation is a core usability feature: users keep seeing the last known successful data while the cache refreshes, and applications can add global network feedback without coupling each screen together.
Sources: docs/framework/angular/guides/background-fetching-indicators.md
Hydration, SSR, and Data Fetching Clients
The supplied Angular data-fetching guide mentions two approaches that matter for server rendering. Angular HttpClient can cache requests performed on the server and prevent unneeded client requests, and this behavior works out of the box for HttpClient. The same guide notes that TanStack Query has its own hydration functionality, which can be more powerful but requires setup. For this reference, the important distinction is responsibility: Angular HttpClient SSR caching belongs to the transport/framework layer, while Query hydration belongs to the query cache lifecycle.
Sources: docs/framework/angular/angular-httpclient-and-other-data-fetching-clients.md
That distinction affects implementation choices. If a team already relies on Angular HttpClient for interceptors, testing helpers, pending-task awareness, and SSR request caching, it can still use TanStack Query as the cache and observer layer by converting observables to promises in queryFn. If the team needs cache-level dehydration and rehydration across server and client, it should use the dedicated TanStack Query hydration APIs documented elsewhere in the first-party docs. The two mechanisms solve overlapping navigation-performance problems, but they operate at different layers and require different setup.
Sources: docs/framework/angular/angular-httpclient-and-other-data-fetching-clients.md
Compact Reference
- Install a client into Angular:
provideTanStackQuery(new QueryClient()). - Install with optional devtools:
provideTanStackQuery(new QueryClient(), withDevtools()). - Defer or share a client through DI: pass an
InjectionToken<QueryClient>toprovideTanStackQuery. - Observe a single query: call
injectQuery(() => ({ queryKey: ['todos'], queryFn: fetchTodos })). - Read query observer state: use accessors such as
isPending(),isError(),isSuccess(),isFetching(),data(), anderror(). - Observe cache-wide background activity: call
injectIsFetching(). - Use Angular
HttpClient: convert its observable withlastValueFromorfirstValueFrominsidequeryFn. - Load Angular devtools automatically in development: import
withDevtoolsfrom the main devtools subpath and leaveloadDevtoolsas'auto'. - Load devtools in controlled production scenarios: import from
@tanstack/angular-query-experimental/devtools/productionand pass aloadDevtoolsoption.
The docs navigation reinforces that these ideas are not Angular-only concepts. docs/config.json places Angular among React, Solid, Vue, Svelte, and Lit framework sections, each with getting-started and capability guides. That structure reflects the project architecture: the core query model is shared, while each adapter exposes idiomatic primitives for its framework. When reading framework docs, translate hook, composable, signal, or controller names back to the same cache contract: query keys identify data, query functions fetch it, clients hold it, and observers render it.
Sources: docs/config.json
Community resources can help teams standardize the parts that sit around the core. The repository docs list utilities such as Query Key Factory for typesafe standardized query keys, GraphQL Code Generator for generated React Query hooks from schemas, Orval for OpenAPI-generated TypeScript clients, and React Query Kit for reusable typed hooks. These tools do not replace the cache or observer contracts, but they can make cache identity and query function creation more consistent across larger applications.
Sources: docs/community-resources.md
Next Steps
Use this page as a bridge between conceptual cache behavior and framework-specific APIs. If you are configuring Angular Query, start with provideTanStackQuery and decide whether the client belongs in main application providers or a lazy-loaded boundary. If you are debugging lifecycle behavior, enable devtools and inspect queries, mutations, freshness, and background fetching. If you are designing data access, standardize query keys and ensure every queryFn returns a promise, even when the underlying client is observable-based.
For deeper API work, read the QueryClient reference next, then the framework adapter page for the UI layer you are using. For user-interface behavior, pair this page with the background refetching and render optimization pages. For server rendering, compare the SSR and hydration guide with Angular HttpClient SSR caching so you choose the correct layer for transfer, deduplication, and client-side reuse.