Photo by Eric Er on Unsplash

On this page

This chapter follows Schema design in GraphQL.

GraphQL is transport-shaped like any HTTP API until a client library adds caching, deduplication, and React bindings. The right choice depends on team size, need for normalized caches, and tolerance for compiler tooling.

Plain fetch and graphql-request

fetch (or axios) with a JSON body is enough for scripts and prototypes:

const res = await fetch("/graphql", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ query: `{ ping }` }),
});

graphql-request wraps the same call with typed helpers and middleware hooks. Neither caches by default nor deduplicates in-flight requests—you add that yourself or move upstack.

urql

urql (v5 on @urql/core 6) targets React, Preact, Svelte, and Vue with a small exchange pipeline: cacheExchange, fetchExchange, optional graphcacheExchange, auth, retry, and subscriptions. Defaults favor simplicity; Graphcache opt-in adds normalized storage. This series dedicates chapters to urql and codegen.

Pick urql when you want a lean client, explicit exchanges, and Guild-friendly tooling without Apollo’s ecosystem weight.

Apollo Client

Apollo Client provides InMemoryCache with field policies, @apollo/client React hooks, local state (legacy), and deep integration with Apollo Router, GraphOS, and persisted queries. The cache is powerful but requires learning typePolicies and possibleTypes for unions.

Pick Apollo when you already run GraphOS, need mature devtools, or standardize on Apollo’s platform across server and client.

Relay

Relay compiles GraphQL at build time with the Relay Compiler, colocates fragments with components, and enforces a strict data-fetching model (useLazyLoadQuery, useFragment, @appendEdge mutations). Modern Relay uses hooks instead of container HOCs.

Pick Relay for very large React codebases that benefit from compiler-enforced fragment colocation and store normalization—accepting compiler and schema compatibility constraints.

TanStack Query with GraphQL

TanStack Query treats each GraphQL operation as a query key + fetch function. You get stale-time, background refetch, and mutations without a GraphQL-specific cache. Pair with GraphQL Codegen for typed documents.

Pick TanStack Query when the team already standardized on it for REST and wants the same patterns for GraphQL without learning Apollo or urql caches.

When to choose which

Need Reasonable default
Script or admin tool fetch / graphql-request
React app, moderate complexity urql + codegen (this series)
Apollo GraphOS, enterprise graph Apollo Client
Strict fragment colocation at scale Relay
Shared data layer with REST TanStack Query

Next: Getting started with urql.

Check your understanding

Question 1 of 6

0 of 6 checked

  1. 1. What do fetch and graphql-request omit out of the box?

Search articles

Type a word to search published articles.

Open the search page