← Back to blog
··14 min read

TanStack Query vs SWR vs RTK Query in 2026: Which Data-Fetching Library to Pick

TanStack QueryReact QuerySWRRTK QueryReactData FetchingNext.jsTypeScript
TanStack Query vs SWR vs RTK Query in 2026: Which Data-Fetching Library to Pick

Three Libraries for One Hard Problem

Fetching data sounds trivial — call an API, show the result. It stops being trivial the moment two components request the same data, a mutation needs to update the UI before the server confirms, a list has to paginate, or the screen has to stay fresh while the user is looking at it. That's when hand-rolled useEffect fetching turns into a pile of loading flags, race conditions, and stale UI.

In 2026, three libraries own the job of managing that server state in React, and they make different bets:

  • TanStack Query (formerly React Query) — the full-featured default. Caching, background refetching, deduplication, mutations with optimistic updates, infinite queries, the best DevTools in the space, and adapters beyond React.
  • SWR — the minimal choice. A single useSWR hook, a tiny footprint, and stale-while-revalidate defaults. From the Next.js team, and a natural fit for read-heavy apps.
  • RTK Query — the Redux-native choice. Data fetching built into Redux Toolkit's store, with auto-generated hooks and a cache-tag invalidation system.
  • Pick the wrong one and the symptoms are familiar: you bolt a second heavyweight dependency onto an app that only displays data, you outgrow SWR's simplicity halfway through a complex mutation flow, or you adopt all of Redux just to get its query layer.

    This guide compares all three through two lenses: which is best to build on, and which produces a codebase that's clean to hand off or sell.

    Analytics data and charts displayed on a screen

    Analytics data and charts displayed on a screen

    First, The Distinction That Makes This Whole Category Make Sense

    Before comparing features, the single most important point: these three libraries manage server state, not client state — and those are different problems.

  • Client state only exists in the browser and you own it completely: which modal is open, the theme, a cart drawer, a multi-step form's progress. That's the job of Zustand, Redux Toolkit, or Jotai.
  • Server state is a local cache of data that actually lives on your API: the user list, the product catalog, an order, dashboard metrics. You don't own it — you borrow a copy that can go stale the moment someone else changes it.
  • Server state needs caching, deduplication, background refetching, and invalidation. The most common architecture mistake in React apps is storing fetched API data in a client-state store by hand, which forces you to reinvent all of that — badly. TanStack Query, SWR, and RTK Query exist precisely so you don't.

    Get this split right and most "our state management is a mess" complaints disappear: a data-fetching library for anything from an API, a light client-state library for browser-only state. That's the wider point of picking a coherent tech stack for web apps in 2026.

    At a Glance

    TanStack QuerySWRRTK Query
    First released2019 (as React Query)20192020
    Comes fromTanStack (Tanner Linsley)Vercel (Next.js team)Redux team
    Core API`useQuery` / `useMutation``useSWR`Auto-generated hooks
    Bundle sizeLarger of the threeSmallestShips with Redux Toolkit
    MutationsFirst-class, richBasic (mutate / trigger)First-class
    Cache invalidationBy query keyBy key / revalidationCache tags
    DevToolsBest-in-classMinimalVia Redux DevTools
    Requires a store/providerProvider onlyNo provider neededRedux store
    Multi-frameworkYes (Vue, Svelte, Solid…)React-focusedReact (Redux)
    Best forFull-featured defaultLightweight, read-heavyExisting Redux apps

    Note: all three are actively maintained and their APIs evolve. Treat this table as a map, not a spec sheet — verify current behaviour against each project's official docs before you commit.

    The Design Decision That Explains Each One

    Almost every practical difference follows from one bet each project made.

    TanStack Query: treat server state as a first-class problem worth a full toolkit

    TanStack Query's bet is that server state is complex enough to deserve a complete, dedicated engine — not a thin fetch wrapper. So it ships caching keyed by a query key, automatic deduplication of identical in-flight requests, background refetching on window focus and reconnect, stale-time and garbage-collection controls, retries, pagination and infinite queries, and mutations with optimistic updates and rollback.

    ts
    // TanStack Query — a query and a mutation that invalidates it
    import {
      useQuery,
      useMutation,
      useQueryClient,
    } from "@tanstack/react-query";
    
    function Todos() {
      const qc = useQueryClient();
    
      const { data, isPending, error } = useQuery({
        queryKey: ["todos"],
        queryFn: () => fetch("/api/todos").then((r) => r.json()),
      });
    
      const addTodo = useMutation({
        mutationFn: (title: string) =>
          fetch("/api/todos", { method: "POST", body: title }),
        // refetch the list once the server confirms
        onSuccess: () => qc.invalidateQueries({ queryKey: ["todos"] }),
      });
    
      if (isPending) return <p>Loading…</p>;
      if (error) return <p>Something went wrong.</p>;
      return <List items={data} onAdd={(t) => addTodo.mutate(t)} />;
    }

    What you get is the widest feature set and the best DevTools in the category — an inspectable panel showing every query, its cache state, and its fetch status. What you pay is the largest bundle of the three and more API surface to learn. It earns its place as the default when your app does real work with server data, not just displays it.

    SWR: make the common case a one-liner

    SWR's bet is the opposite — that for most screens, you just want fresh-enough data with almost no ceremony. Its name is its strategy: stale-while-revalidate. Return the cached value instantly, refetch in the background, update when the new data arrives.

    ts
    // SWR — the whole thing is one hook
    import useSWR from "swr";
    
    const fetcher = (url: string) => fetch(url).then((r) => r.json());
    
    function Profile() {
      const { data, error, isLoading } = useSWR("/api/user", fetcher);
    
      if (isLoading) return <p>Loading…</p>;
      if (error) return <p>Failed to load.</p>;
      return <span>Hello, {data.name}</span>;
    }

    There's no provider to wire up, the bundle is the smallest of the three, and the defaults — dedup, focus revalidation, retry — are sensible out of the box. Coming from the Next.js team, it pairs naturally with Vercel-hosted apps.

    The honest caveat: SWR is deliberately lean. Its mutation story is basic compared to TanStack Query's, and complex flows — heavy optimistic updates, intricate cache manipulation, infinite queries with fine control — are where you start writing code that TanStack Query would have handled for you. SWR is superb until you outgrow it.

    RTK Query: fold data fetching into the store you already have

    RTK Query's bet only pays off under one condition: you're already using Redux Toolkit. If you are, adding a separate data-fetching library means two systems for state. RTK Query instead builds fetching into the Redux store — you define an API slice with endpoints, and it auto-generates typed hooks and manages the cache with a tag system.

    ts
    // RTK Query — endpoints defined once, hooks generated for you
    import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";
    
    export const api = createApi({
      reducerPath: "api",
      baseQuery: fetchBaseQuery({ baseUrl: "/api" }),
      tagTypes: ["Todo"],
      endpoints: (build) => ({
        getTodos: build.query({ query: () => "todos", providesTags: ["Todo"] }),
        addTodo: build.mutation({
          query: (title) => ({ url: "todos", method: "POST", body: { title } }),
          invalidatesTags: ["Todo"], // auto-refetches getTodos
        }),
      }),
    });
    
    export const { useGetTodosQuery, useAddTodoMutation } = api;

    For a team standardized on Redux Toolkit, this is genuinely elegant: one store, cache tags that invalidate cleanly, and no extra dependency. The trap is adopting Redux *just* to get RTK Query — you take on Redux's setup, boilerplate, and bundle weight to solve a problem TanStack Query and SWR solve standalone with less ceremony. RTK Query is the right answer to "we already use Redux," not to "how should I fetch data."

    Mutations and Invalidation: Where The Real Differences Live

    Reading data is the easy 20%. The other 80% is what happens when the user *changes* something and the UI has to stay correct. This is where the three separate most.

  • TanStack Query has the richest mutation model: useMutation with onMutate for optimistic updates, automatic rollback on error, and invalidateQueries to refetch affected data by key. Fine-grained cache updates are first-class.
  • RTK Query is also strong here — its cache-tag system means a mutation declares which tags it invalidates, and every query providing those tags refetches automatically. Very clean once you've defined your tags.
  • SWR keeps mutations simpler: mutate to revalidate or optimistically update a key. It handles the common cases well, but complex optimistic flows take more manual work than in the other two.
  • If your app is mutation-heavy — dashboards where users constantly edit, CRUD-heavy admin panels, anything with optimistic UI — weight TanStack Query or RTK Query. If it's mostly reads with occasional writes, SWR's lighter model is plenty.

    Developer working on data-heavy dashboard code

    Developer working on data-heavy dashboard code

    The Next.js App Router Changes The Question

    Here's the shift that catches people out: in the Next.js App Router, a lot of data fetching moves to the server, *before* any of these libraries is involved.

    Server Components fetch data on the server and render it into the initial HTML. Mutations run through Server Actions. React's own fetch cache and revalidation handle a meaningful slice of caching. For a page that simply displays server data and never mutates it interactively, you may not need TanStack Query or SWR at all.

    Where a client data-fetching library still earns its keep is interactive client state that talks to the server:

  • Infinite scroll and "load more"
  • Polling for live data (metrics, notifications, status)
  • Optimistic updates on a mutation
  • Dependent queries that react to user input (search-as-you-type, filters)
  • Refetch on window focus for always-fresh dashboards
  • The 2026 pattern that gives you both worlds: fetch the initial data in a Server Component, then hydrate it into TanStack Query on the client. The first paint is server-rendered and fast; subsequent interactions get client-side caching, refetching, and mutations. SWR supports a similar fallback-data hydration. Whichever you pick, let the server do the first fetch and let the client library take over for interaction — don't duplicate the work.

    Bundle Size and Performance: What's Real

    Bundle size is a genuine, repeatable difference. SWR is the smallest — a lightweight hook you can drop into a marketing site without a second thought. TanStack Query is larger because it does more; on a data-heavy app already shipping hundreds of kilobytes, the difference is noise, but on a lean site it's worth noticing. RTK Query doesn't add a standalone data-fetching bundle — it rides along with Redux Toolkit, which itself is the heavier baseline.

    Runtime behaviour is more alike than different: all three deduplicate identical requests, cache by key, and revalidate in the background. The performance wins that matter come from configuration, not from the library choice — a sensible staleTime so you don't refetch on every mount, precise query keys so caches don't collide, and not over-fetching. The honest framing: for the vast majority of apps, the library isn't your bottleneck. Your API latency, your render tree, and unmemoized expensive components are.

    TypeScript: All Three Are Good

    In 2026 all three have strong TypeScript support, with different feels.

  • TanStack Query infers types cleanly from your queryFn return type; data is typed end to end, and the discriminated-union status (isPending, isError, isSuccess) narrows nicely.
  • SWR infers from the fetcher's return type with minimal friction — typing a useSWR call is usually effortless.
  • RTK Query is fully typed and, because you define endpoints centrally, generates typed hooks for you — arguably the most "types for free" of the three once the API slice is defined.
  • None will fight you. If you want the language-level reasoning behind caring about this at all, see TypeScript vs JavaScript. And because your data types usually originate at the database, this pairs closely with your ORM choice — see Drizzle vs Prisma for where those types start their journey.

    DevTools and Debugging

    If you debug data flow often, TanStack Query wins this clearly. Its DevTools panel shows every query, its exact cache state, whether it's stale or fetching, and lets you trigger refetches and inspect data live. For a complex app, that visibility saves real hours.

    RTK Query is inspectable through the Redux DevTools — you see the cache in the store, action log included — which is powerful in a Redux context. SWR's tooling is the most minimal; it does the job but there's less to look at.

    For a data-heavy dashboard with many interdependent queries, TanStack Query's DevTools are a genuine reason to weight it.

    Lock-In and Handoff: What Someone Inherits

    If you're building something you'll hand to a client, sell on a marketplace, or leave for a team, your data layer is a big part of what they inherit.

    Two developers reviewing code together at a desk

    Two developers reviewing code together at a desk

    Portable regardless of library: your API, your components, your business logic. All three libraries wrap *access* to server data — the endpoints and the UI move with you.

    Where the inheritance gets opinionated:

  • TanStack Query is the most widely recognized full-featured choice — any React developer has seen useQuery, which lowers perceived risk for a buyer and is the safest default for a template meant to be extended.
  • SWR signals a lean, simple codebase and is instantly readable, which appeals to indie and startup buyers, especially on Next.js starters.
  • RTK Query makes sense to inherit only if the template already centers on Redux Toolkit; otherwise it drags in a store the buyer didn't ask for.
  • The failure mode that actually hurts resale isn't the library choice — it's incoherence: API responses crammed into a client store, hand-rolled useEffect fetching mixed with a real query library, or mutations that don't invalidate their queries so the UI shows stale data after a save. Pick one approach, wire mutations to invalidate the right queries, and show real loading and error states. A coherent data story is part of what separates a template buyers trust from one they abandon — see what makes code production-ready for the rest of that checklist.

    Which One for Which Project

    Choose TanStack Query if:

  • You want the full-featured default — caching, mutations, infinite queries, the works
  • Your app mutates data often and needs optimistic updates with rollback
  • You want the best DevTools for inspecting cache and query state
  • You may target more than React someday (Vue, Svelte, Solid share the core)
  • You're building a template meant to be extended and want the most recognized choice
  • Choose SWR if:

  • Your app is read-heavy — mostly displaying data, rarely mutating
  • You want the smallest bundle and the least configuration
  • You're on Next.js / Vercel and want a tool from the same team
  • You value a one-hook, low-ceremony codebase that's trivial to read
  • You haven't hit the limits that would push you to TanStack Query
  • Choose RTK Query if:

  • You're already using Redux Toolkit for client state
  • You want data fetching inside the same store, no second dependency
  • You like the cache-tag invalidation model and auto-generated hooks
  • Your team already standardizes on Redux conventions
  • If you're still unsure:

    In the App Router, start by letting Server Components fetch what they can, and add a client library only for interactive server state. When you do, the honest default in 2026 is TanStack Query for its feature set and DevTools — reach for SWR when simplicity and bundle size matter more than power, and RTK Query only when you're already on Redux Toolkit.

    The Bottom Line

    There's no universal winner — there's a right data-fetching library for what you're building and who inherits it.

  • "Full-featured default, mutation-heavy app" → TanStack Query
  • "Lightweight, read-heavy site or dashboard" → SWR
  • "Already using Redux Toolkit" → RTK Query
  • "Next.js App Router, mostly server data" → Server Components first, TanStack Query or SWR for the interactive bits
  • "Selling a template that must look production-ready" → TanStack Query for recognition, SWR for a lean Next.js starter
  • Whichever you choose, three habits outlast the decision: keep server data in a data-fetching library and browser-only state in a client-state library, invalidate the right queries after every mutation so the UI never shows stale data, and let the server do the first fetch in the App Router so your first paint is fast. Those cost an afternoon and save a month.

    Ready to turn what you build into income? List your template or app on CodeCudos, see how data fetching fits the wider stack in our best tech stack for web apps in 2026 guide, settle the client-state question with Zustand vs Redux Toolkit vs Jotai, or make sure the whole codebase reads as production-ready.

    Frequently asked questions

    Is TanStack Query the same as React Query?

    Yes. React Query was renamed TanStack Query when the project expanded beyond React to support Vue, Svelte, Solid, and Angular through a shared core with per-framework adapters. In a React codebase you still install and import from the React adapter, and most developers and older tutorials still say 'React Query' — they mean the same library. The rename signals the bigger picture: the caching and synchronization engine is framework-agnostic, and TanStack is a family of tools (Query, Table, Router, Form) that share design philosophy. Practically, if you read 'React Query' anywhere, treat it as TanStack Query for React; the API you use day to day is the same useQuery and useMutation surface.

    Do I need TanStack Query or SWR with the Next.js App Router?

    Less than you did with the Pages Router, but often still yes. In the App Router, Server Components fetch data on the server before the page renders, and mutations run through Server Actions — that covers a large share of straightforward data needs without any client library, and React's fetch cache and revalidation handle much of the caching. Where you still want TanStack Query or SWR is in Client Components that need interactive server state: infinite scroll, polling for live data, optimistic updates on a mutation, dependent queries that react to user input, or a dashboard where the client refetches on window focus. A common 2026 pattern is to fetch the initial data in a Server Component and hydrate it into TanStack Query on the client, so the first paint is server-rendered and subsequent interactions get client-side caching and refetching. If your page only displays server data and never mutates it interactively, you may not need either library at all.

    What is the difference between server state and client state?

    Client state is data that only exists in the browser and that you own completely: which modal is open, the current theme, a multi-step form's progress, a cart drawer's open/closed flag. You set it, you read it, and it has no source of truth outside your app — that is what Zustand, Redux Toolkit, and Jotai manage. Server state is a local cache of data that actually lives on your server: the user list, the product catalog, an order, dashboard metrics. You do not own it; you borrow a copy, and it can go stale the moment someone else changes it. Server state needs caching, background refetching, deduplication, and invalidation — problems TanStack Query, SWR, and RTK Query solve. The single most common architecture mistake is storing fetched API data in a client-state store by hand, which forces you to reinvent all of that badly. Keep the two separate: a client-state library for browser-only state, a data-fetching library for anything that came from an API.

    Is SWR or TanStack Query better?

    Neither is universally better — they sit at different points on the simplicity-versus-power curve. SWR is better when you want the smallest, simplest tool: one useSWR hook, a tiny bundle, sensible stale-while-revalidate defaults, and almost nothing to configure. It shines on read-heavy pages and dashboards where you mostly display data. TanStack Query is better when you need the full feature set: first-class mutations with optimistic updates and rollback, query invalidation by key, infinite and paginated queries, parallel and dependent queries, offline support, and the best DevTools in this space. The honest rule: if you find yourself reaching past what SWR offers — complex mutation flows, fine-grained cache control, multi-framework support — TanStack Query is the natural upgrade. If you never hit those limits, SWR's simplicity is a feature, not a shortcoming.

    Should I use RTK Query instead of TanStack Query?

    Use RTK Query if — and largely only if — you are already using Redux Toolkit for client state. In that case RTK Query is compelling: it lives inside the same store, auto-generates typed hooks from your endpoint definitions, uses a cache-tag system for invalidation, and means you do not add a second dependency. If your app already standardizes on Redux Toolkit, reaching for RTK Query for data fetching is the coherent choice. But adopting Redux Toolkit solely to get RTK Query is usually the wrong trade — you take on Redux's setup, boilerplate, and bundle weight to get a data layer that TanStack Query or SWR provides standalone with less ceremony. The clean decision: already on Redux Toolkit, use RTK Query; not on Redux, choose TanStack Query or SWR and manage client state with something lighter.

    Does the choice of data-fetching library matter when selling a template?

    It matters, because data fetching is where buyers judge whether a template is genuinely production-ready or a demo with hardcoded data. A buyer opening your template looks for real query hooks, proper loading and error states, and cache invalidation on mutations — not fetch calls stuffed into useEffect with manual loading flags. TanStack Query signals a modern, full-featured data layer any React developer recognizes, which lowers perceived risk and is the safest default for a template meant to be extended. SWR signals a lean, simple codebase and pairs naturally with Next.js starters. RTK Query makes sense only if the template already centers on Redux Toolkit. The failure mode that hurts resale is the same one that hurts client state: incoherence — API responses crammed into a client store, hand-rolled fetching mixed with a real query library, or no invalidation so the UI shows stale data after a save. Pick one data-fetching approach, wire mutations to invalidate the right queries, and show real loading and error handling; that is part of what makes a template look worth paying for.

    Related guides

    Browse Quality-Scored Code

    Every listing on CodeCudos is analyzed for code quality, security, and documentation. Find production-ready components, templates, and apps — or sell your own code and keep 90%.

    Browse Marketplace →