Solve the N+1 problem with DataLoader, implement persisted queries, apply query cost analysis, and use field-level caching with @cacheControl.
0 / 5 completed
1 / 5
What is the N+1 problem in GraphQL and why does it occur?
N+1 problem: a naive GraphQL resolver for Post.author calls db.getUser(authorId) for each post. For 100 posts, this is 101 database round-trips. The resolver-per-field architecture of GraphQL makes this easy to introduce accidentally, as each resolver is written independently without visibility into sibling resolver calls.
2 / 5
What is DataLoader and how does it solve the N+1 problem?
DataLoader:const userLoader = new DataLoader(ids => db.getUsersByIds(ids)). Each resolver calls userLoader.load(authorId). DataLoader batches all load() calls made within the current tick into a single getUsersByIds([id1, id2, ...]) call. A per-request DataLoader instance also provides request-scoped caching, preventing duplicate fetches within one query.
3 / 5
What are persisted queries in GraphQL and what performance and security benefit do they provide?
Persisted queries: the client sends {"id": "hash123", "variables": {...}} instead of the full query. The server looks up the pre-registered query. Benefits: smaller requests (especially important for mobile), GET-cacheable (hash in URL enables CDN caching), and security (production only allows registered queries, blocking introspection and ad-hoc query injection).
4 / 5
What is query cost analysis in GraphQL and why is it important for API protection?
Query cost analysis: a query that fetches friends-of-friends-of-friends with pagination could multiply to millions of resolver calls. Libraries like graphql-cost-analysis assign costs to fields (e.g. list fields cost 10× their children). The total cost is calculated before execution; queries exceeding the limit receive a 400 error with an informative message about the cost.
5 / 5
What is field-level caching in GraphQL and how does it differ from HTTP response caching?
Field-level caching: HTTP caching POST requests is difficult. @cacheControl(maxAge: 60) on a field tells the Apollo cache layer how long that field's value is valid. The overall response cache TTL is the minimum TTL of all included fields. This enables fine-grained cache control: fast-changing fields have short TTLs without preventing longer caching of stable fields in the same query.