GraphQL Under-Fetching — Solving the N+1 Problem with Batched Queries
In this tutorial, you will learn about GraphQL Under. We cover key concepts, practical examples, and best practices to help you master this topic.
Under-fetching occurs when an API does not return enough data in a single response, forcing clients to make multiple requests. GraphQL solves this by allowing nested queries that fetch related data in one round-trip.
What You'll Learn
- The N+1 problem in REST APIs
- How GraphQL nested queries prevent under-fetching
- Balancing query depth with performance
Why It Matters
Under-fetching multiplies network requests, increasing latency and complexity. GraphQL's nested query capability eliminates this source of performance problems.
Code Examples
# GraphQL: Fetch user and their posts in one query
query {
user(id: "1") {
name
email
posts {
title
content
comments {
text
author {
name
}
}
}
}
}
// REST under-fetching: Multiple round-trips
// Request 1: Get user
const user = await fetch('/api/users/1').then(r => r.json());
// Request 2-5: Get each post (N+1 problem!)
const posts = await Promise.all(
user.postIds.map(id => fetch(`/api/posts/${id}`).then(r => r.json()))
);
// Request 6-15: Get comments for each post
const comments = await Promise.all(
posts.flatMap(post =>
post.commentIds.map(id => fetch(`/api/comments/${id}`).then(r => r.json()))
)
);
// Total: 15+ HTTP requests!
// GraphQL: One request for everything
const query = `{
user(id: "1") {
name
posts {
title
comments { text }
}
}
}`;
const { data } = await fetch('/graphql', {
method: 'POST',
body: JSON.stringify({ query })
}).then(r => r.json());
// Total: 1 HTTP request!
# Measuring round-trips
import time
# REST approach (many requests)
start = time.time()
user = requests.get('https://api.example.com/users/1').json()
post_ids = [1, 2, 3]
posts = [requests.get(f'https://api.example.com/posts/{pid}').json() for pid in post_ids]
rest_time = time.time() - start
print(f'REST: {1 + len(post_ids)} requests in {rest_time:.2f}s')
# GraphQL approach (one request)
start = time.time()
query = '{ user(id: 1) { posts { title content } } }'
result = requests.post('https://api.example.com/graphql', json={'query': query}).json()
gql_time = time.time() - start
print(f'GraphQL: 1 request in {gql_time:.2f}s')
print(f'Speedup: {rest_time/gql_time:.1f}x')
Common Mistakes
1. Creating Deeply Nested Queries
Deep nesting can cause performance issues. Limit query depth to 3-5 levels.
2. Not Using DataLoader to Batch Database Queries
Without batching, each nested field causes a separate database query.
3. Assuming All Related Data Should Be in One Query
Sometimes separate queries are better for Caching or Lazy Loading.
4. Forgetting About Circular References
Ensure your schema does not allow infinite nesting cycles.
5. Ignoring Query Complexity Limits
Large nested queries can overload your server. Implement complexity analysis.
Practice Questions
- What is the N+1 problem?
- How does GraphQL solve under-fetching?
- What is query depth and why does it matter?
- Can GraphQL queries still cause under-fetching?
- When might separate queries be better than one nested query?
Answers:
- When fetching a list of items requires N additional queries for each item.
- By allowing nested queries that fetch related data in a single request.
- The number of nesting levels. Deep queries can be expensive to resolve.
- No, because the client specifies exactly what data is needed.
- For independent data that is cached separately or loaded on demand.
Challenge: Take a REST API that requires 5+ requests to render a page and design a single GraphQL query that fetches all the data. Compare the total response time before and after.
FAQ
Mini Project
Build a benchmark tool that measures total response time and number of requests for a REST API vs a GraphQL API fetching the same nested data. Generate a report showing the performance difference.
What's Next
Deep dive into GraphQL SDL for schema definition, then learn about object types and field definitions.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro