Skip to content

Request-Level Caching

Understanding request-level caching helps you work with GraphQL confidently. Here you will learn the core ideas behind request-level caching, see working code, and pick up best practices used on real teams.

Request-Level Caching Overview

At its core, request-level caching is about doing one thing well inside your GraphQL project. Once you understand the pattern, you can apply it consistently across features and teams.

Good request-level caching pays off across the whole codebase: fewer surprises, easier testing, and smoother onboarding. The snippet below is a solid starting point.

import DataLoader from 'dataloader';

const userLoader = new DataLoader(async (ids) => {
  const users = await db.users.findByIds(ids);
  return ids.map((id) => users.find((u) => u.id === id));
});

// in a resolver
const author = await userLoader.load(post.authorId);

DataLoader batches and caches lookups to eliminate the N+1 query problem.

Request-Level Caching Example

const typeDefs = gql`
  type Query { hello: String! }
`;
const resolvers = { Query: { hello: () => 'world' } };
const server = new ApolloServer({ typeDefs, resolvers });
  • Start from a minimal Request-Level Caching example and grow it only as needed.
  • Keep configuration explicit so Request-Level Caching behaves the same in every environment.
  • Name things clearly so teammates understand your Request-Level Caching at a glance.
  • Add tests around Request-Level Caching early to lock in expected behaviour.

GraphQL Cheatsheet

Quick GraphQL reference related to request-level caching.

Concept Example Purpose
Schema type Query { user(id: ID!): User } Define the API shape
Resolver Query: { user: (_, { id }) => ... } Provide field data
Query query { user(id: 1) { name } } Read exactly what you need
Mutation mutation { createUser(input) { id } } Change data
Subscription subscription { postAdded { id } } Real-time updates
Context context: ({ req }) => ({ user }) Auth and shared state
DataLoader loader.load(id) Batch to avoid N+1

How Request-Level Caching Works in GraphQL

Request-Level Caching fits into GraphQL's model of a single typed schema that clients query for exactly the data they need. The server resolves each requested field through resolver functions.

DataLoader batches and caches lookups to eliminate the N+1 query problem.

  • The schema is the contract between client and server.
  • Resolvers fetch data field by field, including nested types.
  • Clients request only the fields they use, avoiding over-fetching.
  • Context carries auth and shared services into every resolver.

Practical Guidance for Request-Level Caching

In production, request-level caching should be efficient and secure. Batch data access with DataLoader, guard resolvers with authorization, and limit query depth and complexity.

Concern Recommendation
N+1 queries Batch with DataLoader
Security Auth in context, depth/complexity limits
Errors Typed GraphQLError with extension codes
Performance Cache and paginate large lists

Common Mistakes

  • Skipping error handling and edge cases when wiring up request-level caching.
  • Leaving request-level caching untested, so regressions slip into production.
  • Over-engineering request-level caching before you actually need the extra flexibility.
  • Ignoring documentation, which makes request-level caching hard for the next developer to change.

Key Takeaways

  • Request-Level Caching is a core part of working effectively with GraphQL.
  • Start small and keep request-level caching focused on a single responsibility.
  • Apply consistent patterns so request-level caching scales across your project.
  • Test and document request-level caching to keep it maintainable over time.

Pro Tip

Bookmark this request-level caching pattern and reuse it. Consistency across your GraphQL codebase is worth more than clever one-off solutions.