@urql/core, apollo-client, and graphql-request are tools for interacting with GraphQL APIs, but they serve different architectural needs. @urql/core is a modular, framework-neutral core library that powers the urql ecosystem, offering customizable caching and logic through exchanges. apollo-client is the legacy package for the Apollo GraphQL client, now deprecated in favor of @apollo/client, known for its robust caching and state management features. graphql-request is a minimalistic HTTP client for GraphQL, focusing on simplicity without built-in caching or state management, making it ideal for scripts or server-side usage.
When building applications that rely on GraphQL, choosing the right client library shapes your data flow, caching strategy, and overall code maintenance. @urql/core, apollo-client, and graphql-request represent three distinct approaches to solving this problem. Let's break down how they handle common engineering challenges.
@urql/core uses a modular exchange system to handle caching.
cacheExchange to store results.// @urql/core: Configuring cache exchange
import { createClient, cacheExchange } from '@urql/core';
const client = createClient({
url: '/graphql',
exchanges: [cacheExchange, fetchExchange]
});
apollo-client (Legacy) includes a powerful normalized cache out of the box.
@apollo/client.// apollo-client: Legacy cache setup
import ApolloClient from 'apollo-client';
import { InMemoryCache } from 'apollo-cache-inmemory';
const client = new ApolloClient({
uri: '/graphql',
cache: new InMemoryCache()
});
graphql-request does not include caching or state management.
// graphql-request: No built-in cache
import { request } from 'graphql-request';
const query = `{ user { id } }`;
const data = await request('/graphql', query);
// Manual caching required elsewhere
@urql/core balances flexibility with simplicity.
// @urql/core: Custom exchange setup
import { createClient, fetchExchange } from '@urql/core';
const client = createClient({
url: '/graphql',
exchanges: [fetchExchange]
});
apollo-client requires more initial configuration.
// apollo-client: Legacy link setup
import { createHttpLink } from 'apollo-link-http';
import ApolloClient from 'apollo-client';
const link = createHttpLink({ uri: '/graphql' });
const client = new ApolloClient({ link });
graphql-request has the lowest setup barrier.
// graphql-request: Minimal setup
import { GraphQLClient } from 'graphql-request';
const client = new GraphQLClient('/graphql');
const data = await client.request(query);
@urql/core is actively maintained.
@urql/react.// @urql/core: Current standard usage
import { createClient } from '@urql/core';
// Actively developed by Formidable
apollo-client is officially deprecated.
// apollo-client: Deprecated warning
// npm install apollo-client // DO NOT USE
// Use @apollo/client instead
graphql-request is actively maintained.
// graphql-request: Current standard usage
import { request } from 'graphql-request';
// Actively maintained community project
All three tools work well with GraphQL code generators like graphql-code-generator, but integration differs.
@urql/core supports typed clients via plugins.
// @urql/core: Typed query
import { typedClient } from './generated';
const result = await typedClient.query(UserQuery);
apollo-client supports TypeScript natively.
// apollo-client: Typed query (Legacy)
import { gql } from 'apollo-client';
const query = gql`{ user { id } }`;
graphql-request generates typed SDKs easily.
// graphql-request: Generated SDK
import { getSdk } from './generated';
const sdk = getSdk(client);
const { user } = await sdk.GetUser();
While the differences are clear, these libraries share some core capabilities.
// All support variables
const variables = { id: 1 };
// urql: client.query(query, variables)
// apollo: client.query({ query, variables })
// request: request(url, query, variables)
// All support headers
// urql: context in operation
// apollo: link middleware
// graphql-request: headers in constructor
// All import via npm
import { ... } from 'package-name';
| Feature | @urql/core | apollo-client | graphql-request |
|---|---|---|---|
| Status | β Active | β Deprecated | β Active |
| Caching | ποΈ Modular (Exchange) | ποΈ Built-in (InMemory) | β None |
| Setup | βοΈ Medium | βοΈ High | βοΈ Low |
| Framework | π§© Neutral (Core) | βοΈ React Focused (Legacy) | π Universal |
| Bundle Size | π¦ Small | π¦ Large | π¦ Minimal |
@urql/core is like a customizable engine ποΈβgreat for teams that want control over how data flows without being locked into a specific framework. It shines when you need to build custom bindings or want a lighter alternative to Apollo.
apollo-client is like a legacy enterprise system π’βpowerful but outdated. Do not use it for new work. If you need its feature set, migrate to @apollo/client.
graphql-request is like a lightweight utility knife πͺβperfect for simple tasks, server-side scripts, or when you want to handle caching yourself. It removes magic and gives you raw control.
Final Thought: For new frontend applications, avoid apollo-client entirely. Choose @urql/core if you want a balanced, modern client with caching. Choose graphql-request if you prefer minimalism and plan to manage state elsewhere.
Choose @urql/core if you need a flexible, framework-neutral GraphQL client with customizable caching and logic. It is ideal for teams that want to build custom bindings for specific frameworks or need fine-grained control over request handling without the heavy footprint of larger libraries.
Do NOT choose apollo-client for new projects as it is officially deprecated. Instead, evaluate @apollo/client if you need a feature-rich client with advanced caching, state management, and strong React integration. It suits large-scale applications requiring complex data synchronization.
Choose graphql-request if you need a lightweight, zero-dependency client for simple queries, server-side scripts, or when you plan to manage caching and state with other tools like React Query. It is perfect for scenarios where minimal setup and raw HTTP control are priorities.
The shared core for the highly customizable and versatile GraphQL client, urql
More documentation is available at formidable.com/open-source/urql.