Apollo 21: DevTools & Debugging
easy⏱ 5 mincourseapollo
What Apollo DevTools shows
Apollo Client DevTools is a browser extension (Chrome/Firefox) with three main panels:
- Queries: Shows all active queries, their variables, loading state, and results. You can re-run queries from here.
- Mutations: Lists executed mutations with their variables and results.
- Cache: Visualizes the entire
InMemoryCache as a normalized object tree. Each entry shows its cache ID (User:5), fields, and references. This is invaluable for debugging why a component isn't re-rendering — if the data isn't in cache, the query hasn't resolved.
DevTools also lets you modify cache entries directly, which is powerful for testing edge cases without changing server data.
// Enable DevTools in development
const client = new ApolloClient({
link: httpLink,
cache: new InMemoryCache(),
connectToDevTools: process.env.NODE_ENV === 'development',
});
// DevTools are automatically connected when:
// 1. The browser extension is installed
// 2. connectToDevTools is true (default in dev)
// 3. window.__APOLLO_CLIENT__ is set
Debug a cache issue
Create a component that fetches a user list and a user detail. After updating the user's name via mutation, the list still shows the old name. Debug this using the DevTools cache inspector. The issue is that the list query returns name but the mutation returns id and email only — the cache entry for the user doesn't have the updated name. Fix the mutation to also return name, or use refetchQueries to refresh the list.
Logging link for request tracing
A logging link sits in your link chain and logs every operation. It captures the operation name, type (query/mutation/subscription), variables, timing, and any errors. In development, log to console. In production, send to your monitoring service (DataDog, Sentry, etc.). Place the logging link first in the chain to capture the complete operation lifecycle including retries.
const loggingLink = new ApolloLink((operation, forward) => {
const { operationName } = operation;
const start = performance.now();
console.log(`[Apollo] Start: ${operationName}`, operation.variables);
return forward(operation).map(response => {
const duration = Math.round(performance.now() - start);
console.log(`[Apollo] Done: ${operationName} (${duration}ms)`);
if (response.errors) {
console.warn(`[Apollo] Errors in ${operationName}:`, response.errors);
}
return response;
});
});
Cache normalization debugging
Most Apollo bugs come down to cache normalization. Common issues:
- Missing
id in query selection: If you don't select id for a type, Apollo can't normalize it and treats it as an embedded object.
- Missing
__typename: Without __typename, cache lookups fail. Apollo adds it automatically unless addTypename is false.
- Mutation doesn't return updated fields: The cache only updates fields present in the mutation response. Always return the same fields your queries select.
- Custom keyFields not configured: If your type uses
sku instead of id, you need typePolicies: { Product: { keyFields: ['sku'] } }.
DevTools cache inspector reveals all of these instantly.