GraphQL in Production · Performance and Caching

Client Caching and State

Normalized caches, cache policies and updates after mutations.

GraphQL clients (Apollo Client, urql with Graphcache, Relay) keep a normalized cache keyed by __typename + id. After mutations, objects returned in payloads update automatically; list membership changes (add/remove) need explicit cache updates or refetching. Choose fetch policies per query: cache-first for stable data, cache-and-network for freshness, network-only for sensitive data. On mobile, persist the cache for offline startup.

Common fetch policies

Fetch policy Behavior Use for
cache-first Cache if present, else network Stable reference data
cache-and-network Return cache, then refresh Feeds, dashboards
network-only Always network, writes cache Must-be-fresh screens
no-cache Network, doesn't store Sensitive data
// Apollo Client: update a list after a mutation
const [addItem] = useMutation(ADD_CART_ITEM, {
  update(cache, { data }) {
    cache.modify({
      id: cache.identify({ __typename: "Cart", id: data.addCartItem.cart.id }),
      fields: { items: (existing = []) => [...existing, cache.writeFragment({ data: data.addCartItem.item, fragment: CART_ITEM })] },
    });
  },
  optimisticResponse: { addCartItem: { __typename: "AddCartItemPayload", cart: { __typename: "Cart", id: cartId }, item: { __typename: "CartItem", id: "temp", quantity: 1 } } },
});

Common pitfalls

  • Missing id fields in selections (objects can't be normalized).
  • Forgetting list updates after create/delete.
  • Caching sensitive data persistently on devices.

Key points

  • Normalized by __typename + id
  • Payloads update caches; lists need help
  • Pick fetch policies per screen

Further reading: Apollo Client: Caching

Practice questions

Why should every selection include the id field?

Answer

Normalized caches identify objects by type and id; without it, objects can't be merged or updated after mutations.

What does an optimistic response do?

Answer

It writes the expected mutation result to the cache immediately so the UI updates instantly, then replaces it with the real server response (or rolls back on error).

Open in the app to mark lessons complete, take notes and track your progress.