How to Cache GraphQL Queries Efficiently
To cache
GraphQL queries, use client-side caching libraries like Apollo Client or Relay that store query results locally. On the server side, implement caching with tools like DataLoader or HTTP caching headers to avoid repeated data fetching and speed up responses.Syntax
GraphQL caching involves setting up cache policies and storing query results. On the client, you configure cache behavior when creating the client instance. On the server, you can cache data loaders or HTTP responses.
- Client-side cache: Configure cache policies like
cache-first,network-only, orcache-and-network. - Server-side cache: Use
DataLoaderto batch and cache database requests or set HTTP cache headers.
javascript
import { ApolloClient, InMemoryCache } from '@apollo/client'; const client = new ApolloClient({ uri: 'https://example.com/graphql', cache: new InMemoryCache(), defaultOptions: { watchQuery: { fetchPolicy: 'cache-first', }, query: { fetchPolicy: 'cache-first', }, }, });
Example
This example shows how to set up Apollo Client with caching and how to use DataLoader on the server to cache database calls.
javascript
// Client-side Apollo Client setup import { ApolloClient, InMemoryCache, gql } from '@apollo/client'; const client = new ApolloClient({ uri: 'https://example.com/graphql', cache: new InMemoryCache(), }); // Query with caching client.query({ query: gql`query GetBooks { books { id title } }`, fetchPolicy: 'cache-first', }).then(result => console.log(result.data)); // Server-side DataLoader example import DataLoader from 'dataloader'; const bookLoader = new DataLoader(async (ids) => { // Simulate batch database fetch const books = await fetchBooksByIds(ids); return ids.map(id => books.find(book => book.id === id)); }); async function fetchBooksByIds(ids) { // Simulated DB call return [ { id: '1', title: 'Book One' }, { id: '2', title: 'Book Two' }, ].filter(book => ids.includes(book.id)); }
Output
{ books: [ { id: '1', title: 'Book One' }, { id: '2', title: 'Book Two' } ] }
Common Pitfalls
Common mistakes when caching GraphQL queries include:
- Not setting the correct
fetchPolicy, causing stale or no cache usage. - Ignoring cache invalidation, leading to outdated data shown to users.
- Over-caching server responses without considering data changes.
- Not batching requests on the server, causing redundant database calls.
Always balance cache freshness with performance.
javascript
/* Wrong: Using 'network-only' fetchPolicy disables cache */ client.query({ query: gql`query GetBooks { books { id title } }`, fetchPolicy: 'network-only', // always fetches from server }); /* Right: Use 'cache-first' to use cache if available */ client.query({ query: gql`query GetBooks { books { id title } }`, fetchPolicy: 'cache-first', });
Quick Reference
| Concept | Description | Example |
|---|---|---|
| Client Cache Policy | Controls how queries use cache or network | fetchPolicy: 'cache-first' |
| DataLoader | Batches and caches server data fetching | new DataLoader(batchFunction) |
| HTTP Cache Headers | Cache responses at HTTP level | Cache-Control: max-age=60 |
| Cache Invalidation | Update or clear cache when data changes | Refetch queries or update cache manually |
Key Takeaways
Use client-side caching libraries like Apollo Client with proper fetch policies to cache GraphQL queries.
Implement server-side caching with DataLoader to batch and cache database requests efficiently.
Set HTTP cache headers to leverage browser and proxy caching when possible.
Avoid stale data by managing cache invalidation carefully after data updates.
Test caching behavior to ensure data freshness and performance balance.