03 / 03

Discuss server side caching in graphql.

Difficulty: 5/10
cache invalidation, resolver-level caching, TTL & eviction

Server-side caching is crucial for reducing database load, lowering latency, and can be implemented at a few different levels.

  1. 1

    Resolver-Level Caching with DataLoader

  2. 2

    Operation-Level (Response) Caching

  3. 3

    Persisted Queries

  4. 4

    Persistent Caching and CDNs

  5. 5

    Middleware-Level Caching

Resolver-Level Caching with DataLoader: This is your first line of defense. It prevents the infamous N+1 problem (e.g., fetching a list of 100 posts, then making 100 separate author queries) by batching and caching requests in a single request cycle. The DataLoader utility is key here, but it's crucial to create a new DataLoader instance for each incoming request to prevent data leakage between different users. While primarily for batching, DataLoader includes a basic per-request cache to avoid duplicate lookups for the same key within a single GraphQL operation

Operation-Level (Response) Caching: A more advanced technique that caches the results of entire GraphQL queries based on their query string and variables. For example, the cache key might look like hash(operationString, stringify(variables)). To be safe for user-specific data, the cache key must also incorporate a requestor-specific identifier like a user ID to prevent serving one user's data to another. Because invalidating this cache can be complex, many teams start with a simple Time To Live (TTL) strategy before building more sophisticated, mutation-triggered invalidation logic

Persisted Queries: This technique dramatically shrinks request payloads and enables GET-based caching. The client sends a short, unique hash (e.g., SHA-256) instead of the full query string to the server, which looks up the original query from its cache. This works with both POST and GET methods. Paired with a CDN, it allows for extremely fast responses, especially for large, complex queries

Persistent Caching and CDNs: For requests that are truly public (e.g., product listings), you can leverage a CDN. Because many CDNs don't cache POST requests by default, you must use GET requests. Combined with "Persisted Queries" (to reduce URL length), and standard HTTP Cache-Control headers, you can enable powerful CDN-level caching. Apollo Server's response caching plugin also provides cache tags that work like CDN surrogate keys for granular invalidation

Middleware-Level Caching: You can also cache at the HTTP middleware level by integrating a caching library (like graphql-redis-cache) to store query results in a distributed cache like Redis before they reach the GraphQL execution engine

Scenario Questions

0-2 years experience

  1. 1We have a GraphQL query that fetches a list of products. How would you add server‑side caching to reduce load on the database for repeated requests?
  2. 2If you enable caching on a resolver that returns user profile data, what happens when the user updates their profile? How would you ensure the cache stays correct?
  3. 3Your GraphQL server uses an in‑memory cache with a TTL of 5 minutes. What would a client see if they request the same data after 3 minutes versus after 6 minutes?

2-5 years experience

  1. 1We introduced a cache layer for a product‑search resolver, but after a deployment some users see stale results. Walk me through how you'd debug the issue.
  2. 2Explain the trade‑offs between caching at the field level versus caching the whole query response in a GraphQL API.
  3. 3Our service uses Apollo Server with DataLoader and Redis cache. How would you decide which data to cache in Redis versus relying on DataLoader's request‑level batching?

5-8 years experience

  1. 1Design a server‑side caching strategy for a GraphQL API that serves both public catalog data and private user‑specific data, considering cache invalidation, security, and scale.
  2. 2How would you handle cache eviction and consistency for a GraphQL mutation that updates multiple related entities across services?
  3. 3Discuss how you would integrate CDN edge caching with persisted GraphQL queries to improve latency while respecting per‑user auth.

8+ years experience

  1. 1Our company is migrating from a monolithic GraphQL server to a federated architecture. What changes would you make to the caching approach to support cross‑service data freshness and avoid cache fragmentation?
  2. 2Describe a long‑term plan for evolving cache policies (TTL, stale‑while‑revalidate, etc.) across many teams that own different parts of the schema, ensuring observability and governance.
  3. 3If a legacy service cannot be modified to emit cache‑control headers, how would you design a wrapper or proxy to enforce consistent caching across the GraphQL gateway?

Follow-up Questions

  • What metrics would you monitor to know the cache is effective?
  • How would you handle a scenario where a cache miss triggers many downstream calls?
  • Can you give an example of a cache‑control header you might send from a resolver?
Share

Share via WhatsApp, X, Facebook, LinkedIn or copy link. Open Graph preview enabled.