
Choosing between React Query (now TanStack Query) and SWR in 2026 comes down to one question: do you need a full data-fetching cache or just a clean way to get fresh data into components? If your app leans on complex mutations, optimistic UI, infinite scroll, and serious cache control, TanStack Query wins. If you live inside Next.js, want a 5KB bundle, and most of your reads are "fetch this, keep it fresh," SWR wins. Here's the honest breakdown.
SWR ships at roughly 5.3KB minified and gzipped. TanStack Query is around 16.2KB, three times larger. For most apps that does not matter. For a marketing site with a logged-in dashboard tucked behind a route, or a mobile-first PWA where every kilobyte you save is half a frame of TTI, it absolutely matters.
SWR is also the simplest API in the category. The full mental model is one hook:
const { data, error, isLoading } = useSWR('/api/user', fetcher)
That is it. A junior engineer reads the SWR docs in an afternoon and ships their first feature the same day. By contrast, TanStack Query's object-based API (useQuery({ queryKey, queryFn, staleTime, gcTime, refetchOnWindowFocus, ... })) gives you more knobs but also more chances to misconfigure stale-time and end up with a screen that never refetches.
SWR is maintained by Vercel and slots into Next.js naturally. Server Components plus SWR for client revalidation is a well-trodden path the Vercel docs themselves push. If your stack is Next.js App Router on Vercel, SWR is the path of least resistance.
What SWR is genuinely better at:
suspense: true flag has been stable longer than TanStack's, though both work in 2026.Where SWR struggles: complex mutation flows, anything you'd describe as "I need to surgically invalidate three queries and seed two more after this POST," and offline support. SWR has no offline mutation queue. TanStack Query does.
TanStack Query (the artist formerly known as React Query, rebranded in 2022 when Tanner Linsley moved his other libraries under the same umbrella) is the more powerful tool. It is heavier on bundle, heavier on API, and the depth pays off the moment your app stops being a list-and-detail CRUD UI.
The four things TanStack actually does better:
useMutation with onMutate for optimistic updates, onSettled for rollback, and queryClient.invalidateQueries for surgical cache busts. SWR's mutate works but you write more glue code to get the same ergonomics.useInfiniteQuery is purpose-built. SWR's useSWRInfinite exists but is fiddlier and doesn't handle bidirectional pagination as cleanly.TanStack is also framework-agnostic. The same primitives back @tanstack/vue-query, @tanstack/svelte-query, and @tanstack/solid-query. If your team ships across multiple frameworks, that consistency matters.
| Factor | TanStack Query | SWR |
|---|---|---|
| Bundle size (min+gzip) | ~16.2KB | ~5.3KB |
| API style | Object config (useQuery({ ... })) | Positional (useSWR(key, fetcher)) |
| First-party devtools | Yes, excellent | No |
| Mutation ergonomics | Best in class with useMutation | Workable via mutate, more glue code |
| Infinite queries | useInfiniteQuery, bidirectional | useSWRInfinite, basic |
| Offline mutation queue | Yes | No |
| Suspense | Yes (stable) | Yes (stable) |
| Maintainer | TanStack (independent OSS) | Vercel |
| Best fit | Complex apps, heavy mutations, multi-framework teams | Next.js apps, small bundles, read-heavy UIs |
Notice the table is not slanted. Each column has wins. Treat anyone who tells you one is strictly better than the other with skepticism.
This is the part the top 10 SERP results miss. In 2026, if you're on Next.js App Router or React Router 7's framework mode, a huge chunk of your data fetching has moved to the server. React Server Components fetch directly. loader functions in React Router fetch directly. There's no client cache to manage because there's no client fetch happening.
The honest 2026 stack for a lot of apps looks like this:
router.refresh() for mutations that the server handles end-to-end.If your app is 90% server-rendered with a small interactive island that updates every 30 seconds, SWR is overkill and TanStack is doubly so. A useEffect with a setInterval and a fetch is fine. Don't add a 16KB dependency to solve a problem you don't have.
This is the same calculus we walk through in our breakdown of Vercel vs Cloudflare Pages, where the right answer often turns on whether you're going all-in on a framework or staying portable.
Pick the one that matches your dominant constraint. If you're starting a new Next.js project today and you're not sure, start with SWR. The migration to TanStack Query is mechanical (fetcher signatures change, query keys move into config objects) and rarely takes more than a day for a mid-sized app. The reverse migration is identical effort.
If you already have one in production, do not switch unless you've hit a specific wall. "TanStack has more stars on GitHub" is not a wall. "Our optimistic update logic is 200 lines of glue and our PMs are still seeing flicker" is a wall.
If you're trying to decide and your team is small, the fastest unblock is to spec the actual screens with their data dependencies, then have a senior engineer pick the library with that spec in hand. We see this pattern often on Cadence, where founders book a senior or lead engineer for a week to settle stack questions before committing. Every engineer on Cadence is AI-native by default, vetted on Cursor, Claude Code, and Copilot fluency before they unlock bookings, so they can prototype both libraries in a day and give you a recommendation grounded in your actual app, not a blog post. Senior is $1,500/week, lead is $2,000/week, and the 48-hour trial means you can have the answer by Wednesday.
For a deeper take on how to think about which framework primitives to bet on, our writeup on Django vs FastAPI in 2026 covers the same "shipping velocity vs control" tradeoff on the backend.
This is heretical but worth saying. If your app makes 4 fetches and you have full control over the API shape, a 30-line custom hook with useState, useEffect, and a tiny in-memory Map for caching covers it. No library, no bundle, no upgrade path. The reason to reach for SWR or TanStack is when you've outgrown that hook, not before.
The pattern looks like this:
const cache = new Map()
function useFetch<T>(url: string): { data?: T; error?: Error } {
const [state, setState] = useState({ data: cache.get(url), error: undefined })
useEffect(() => {
fetch(url).then(r => r.json()).then(data => {
cache.set(url, data)
setState({ data, error: undefined })
}).catch(error => setState({ data: undefined, error }))
}, [url])
return state
}
This is fine for a lot of apps. It's not fine for an app that needs revalidation, deduping, optimistic updates, or a devtools view of cache state. Know which you are before adding the dependency.
Trying to settle a stack debate in your team? Book a senior engineer on Cadence for a week and have them prototype both options in your codebase. 48-hour free trial, weekly billing, replace any week. See how Cadence works for founders.
Yes, and it's usually a one-day job for a mid-sized app. The mental model maps cleanly: SWR keys become TanStack queryKey arrays, fetchers move into queryFn, and mutate calls become queryClient.invalidateQueries. The reverse migration is the same effort. Don't pick based on "what if we need to switch."
Runtime performance is effectively identical for typical apps. Both deduplicate requests, both cache responses, both render in similar paint windows. The real performance question is bundle size, where SWR wins (5.3KB vs 16.2KB), and that only matters if you're shipping to a strict performance budget.
Yes. SWR is actively maintained by Vercel and ships with new Next.js releases. The cadence is slower than TanStack Query, which is normal for a more focused library. Slow does not mean abandoned.
Yes. The library was renamed in 2022 from react-query to @tanstack/react-query. Code written for React Query v3 needs a migration to v4+, but the concepts are identical. Most teams migrated within a year of the rename.
Often, no. React Server Components handle initial data fetching server-side, and Server Actions handle most mutations. You only need a client cache library for genuinely interactive client state: polling, optimistic updates, infinite scroll, or live dashboards. For static-leaning apps, you can ship App Router with zero client data libraries. See our take on picking the right Vercel vs Cloudflare deploy for the broader framework calculus.
RTK Query (part of Redux Toolkit) is a third option worth knowing. Pick it if you're already deep in Redux and want one tool for state plus fetching. Skip it if you're not on Redux already. It's not better than TanStack or SWR in isolation, just different scope. The Sentry vs Datadog choice follows similar logic: pick the tool that matches the stack you already have, not the one with the longest feature list.