Apollo 15: Performance Optimization
easy⏱ 5 mincourseapollo
@defer, BatchHttpLink, persisted queries
Three powerful optimization techniques:
- @defer: A directive that tells the server to send part of the response later. Critical data arrives first, deferred fields stream in after:
user { name posts @defer { title } }. The component re-renders as each deferred chunk arrives.
- BatchHttpLink: Combines multiple GraphQL operations sent within a short window into a single HTTP request. Reduces connection overhead when components fire many queries simultaneously.
- Persisted queries: Instead of sending the full query string, send a hash. The server looks up the query by hash. Saves bandwidth (queries can be 10KB+) and adds a security layer.
// @defer directive
const GET_USER = gql`
query GetUser($id: ID!) {
user(id: $id) {
name
email
... @defer {
posts {
id
title
}
analytics {
views
followers
}
}
}
}
`;
Configure batching and APQ
Create an Apollo Client using BatchHttpLink instead of HttpLink. Set batchMax: 5 and batchInterval: 20 for optimal batching. Add createPersistedQueryLink from @apollo/client/link/persisted-queries before the batch link. Use sha256 from crypto-hash for the hash function. Test with a component that fires multiple queries on mount.
useFragment for fine-grained reactivity
By default, when any field in a query result changes, every component using that query re-renders. useFragment subscribes to a single fragment on a specific cache entity. It only re-renders when that fragment's fields change. Use it for list items: each TodoItem subscribes to its own TodoFields fragment, so checking off one todo doesn't re-render the entire list.
import { useFragment } from '@apollo/client';
const TODO_FIELDS = gql`
fragment TodoFields on Todo {
id
title
completed
}
`;
function TodoItem({ id }) {
const { data } = useFragment({
fragment: TODO_FIELDS,
from: { __typename: 'Todo', id },
});
// Only re-renders when THIS todo's fields change
return <li>{data.title}</li>;
}
Federation overview for scaling
For large-scale applications, Apollo Federation lets you split your graph across multiple services (subgraphs). Each team owns a subgraph (users, products, orders) and a gateway (Apollo Router) composes them into a single graph. Clients query the gateway as if it's one schema. Federation is about team autonomy — teams can deploy independently while maintaining a unified API for the frontend.
Measuring Apollo performance
Use Apollo Client Devtools to inspect cache contents, track query timing, and debug cache misses. In production, use ApolloLink to log operation durations. Monitor cache hit rates — if cache-first queries always miss, check your keyFields and type policies. A well-tuned Apollo cache should serve 60-80% of reads from cache in typical apps.