SpikeMe
← Comparisons
Data fetching

TanStack Query vs SWR

updated on July 13, 2026

TanStack Query vs SWR

TanStack Query and SWR compared on cache model, mutations, devtools, and API surface — with real npm data and a verdict by context.

FactTanStack QuerySWR
Current version5.101.22.4.2
Downloads/week (npm)61,168,81213,236,910
LicenseMITMIT
Bundle (gzip)13.3 kB5 kB
CriterionTanStack QuerySWR
Cache and invalidationcache by query key with granular invalidation via queryClientcache by fetcher key with automatic revalidation on focus/reconnect
Mutationsfirst-class useMutation with callbacks and its own cacheno mutation hook in the core package — uses global mutate() or the useSWRMutation addon
DevToolsofficial devtools in a separate packageno official devtools in the core package
Paginationdedicated useInfiniteQuerymanual pattern with a dynamic per-page key
Supported frameworksReact, Vue, Svelte, Solid and Angular via adaptersReact as the main target
Retry and backoffconfigurable per query with built-in exponential backoffconfigurable globally via errorRetryCount/errorRetryInterval
API philosophybroad surface — queries, mutations, infinite, prefetch, hydrationminimal surface centered on a single hook

Context

SWR takes its name from the HTTP pattern it implements — stale-while-revalidate: show the cached value immediately and fire a revalidation in parallel, updating the UI when the response arrives. TanStack Query (formerly React Query) grew out of the same problem — fetching async data in React components without rewriting the same loading, error, cache, and background-revalidation logic on every screen — but was built as a more complete cache layer, with its own client, query lifecycle, and a set of primitives for mutations that SWR leaves out of the core.

The most visible difference isn't technical, it's scope: SWR was designed by Vercel to stay small and do one thing well — fetch and revalidate. TanStack Query was designed to grow alongside the application, covering normalized cache, infinite scroll, optimistic mutations, and devtools, and today has adapters beyond React — Vue, Svelte, Solid, and Angular share the same core. That difference in ambition already shows up at install time: TanStack Query requires a QueryClientProvider wrapping the component tree before any useQuery works, while SWR runs with no provider required, with an implicit global cache keyed by key.

When to choose TanStack Query

TanStack Query pays off when the application does more than read data: it also writes, and those writes need to invalidate or update the cache predictably. The useMutation hook is a first-class citizen, with callbacks (onSuccess, onError, onSettled) and direct integration with queryClient to invalidate the affected queries:

import { useMutation, useQueryClient } from "@tanstack/react-query";

const queryClient = useQueryClient();
const { mutate } = useMutation({
  mutationFn: updateTodo,
  onSuccess: () => queryClient.invalidateQueries({ queryKey: ["todos"] }),
});

That centralized queryClient is what powers the more advanced features: useInfiniteQuery for pagination and infinite scroll without manually reimplementing page accumulation, route prefetching, cache hydration from the server, and official devtools that show the state of each query — fresh, stale, fetching, inactive — in real time during development. The cost is conceptual: to get value from the tool, the team needs to understand query keys, stale time, cache time, and the difference between invalidating and refetching a query, concepts that don't exist in SWR's vocabulary.

When to choose SWR

SWR fits when what the application needs is, in practice, to fetch data and keep it fresh — without building a layer of mutations, pagination, or elaborate hydration on top of that. A single hook covers most cases:

import useSWR from "swr";

const { data, error, isLoading } = useSWR("/api/todos", fetcher);

By default, SWR already revalidates on window focus, on network reconnect, and at configurable intervals, which covers much of what teams normally reimplement manually with raw fetch. For mutations, the library offers two paths: the global mutate() function, which updates a specific key's cache from outside the component, and the useSWRMutation addon, which packages a mutation as its own hook when the global pattern isn't enough. Neither one tries to be as complete as TanStack Query's useMutation — and that economy of concepts is exactly what keeps SWR simple to audit even in a large codebase, since any developer can follow the data flow without learning a cache-specific vocabulary.

Verdict

Both libraries solve the same fetching pain with quality and active maintainers behind them — Vercel in SWR's case, the TanStack team on the other. What really changes is how much cache infrastructure the application already needs today, not a year from now: if the product has write-heavy screens, paginated lists, and teams used to cache devtools, TanStack Query's larger surface pays off early. If what exists is a handful of read calls that just need to stay up to date without drama, adding a dedicated cache client for that is solving a problem the application doesn't have yet — and that's where SWR's economy of concepts is worth more than any extra feature.

TanStack Query

Choose TanStack Query if…

Choose TanStack Query if the project has (or will have) complex mutations, infinite pagination, and a cache that needs fine-grained control, and the team doesn't mind learning a broader API.

SWR

Choose SWR if…

Choose SWR if you want the minimum set of concepts for data revalidation in React, with no dedicated cache client and no separate mutations API.

The numbers above came from the registry, with source and date. Still, this comparison is generic: the right answer depends on versions, your team and what already exists in your project.

Generate the spike for YOUR stack

Share

XLinkedIn