Hello @LelouchRevolution,
When it comes to GraphQL, there are a few common strategies to build a screen in React. Each one has trade-offs depending on your use case:
1. Batch GraphQL operations
This is a middle ground where multiple queries are sent in a single HTTP request (batching).
- You make one HTTP request
- The server processes multiple operations inside it
- You get a single combined response (not multiple responses)
This helps reduce network overhead compared to multiple requests, but:
- It doesn’t improve perceived performance (you still wait for everything)
- It’s more of a transport optimization than a real UI/data-fetching strategy
Important:
- Your server must support batching for this to work
If you’re using Apollo Client / Apollo Server, you’re covered, since Apollo supports batching (with proper setup).
2. Multiple requests
Here, you split your data fetching into separate queries. The advantage is:
- Each request resolves independently
- You can render parts of the UI as soon as each request finishes
But there’s an important downside when it comes to scale:
- If your application grows, the number of requests can become a problem if your infrastructure can’t handle it well
For example:
- Imagine 100k daily users
- Your home screen makes 10 requests
That’s 1 million requests per day just for a single screen, which can put significant pressure on your backend, gateways, and network.
Other downsides:
- More network overhead (multiple round trips)
- Harder to coordinate loading and error states
- Possible duplicated logic across queries
3. Big query (single request) + @defer
This is usually the best approach.
You fetch everything the screen needs in one GraphQL query, which gives you:
- Less network overhead
- A more “GraphQL-native” approach
- Better scalability with fragment colocation
- Each component declares its own data requirements via fragments
- Easier to maintain and evolve as the app grows
- Reduces coupling between UI and data fetching logic
The classic downside is that the response waits for the slowest field. For example, with me, products, and cart:
metakes ~1sproductstakes ~2scarttakes ~3s
Without @defer, the full response would only arrive after 3 seconds.
But with @defer, you can keep a single request and receive multiple incremental responses:
mearrives first (~1s)productsnext (~2s)cartlast (~3s)
This allows progressive rendering while keeping all the benefits of a single query.
Example using @defer
query HomeScreenQuery {
... @defer {
me {
id
name
}
}
... @defer {
featuredProducts {
id
title
products {
id
name
image
price
}
}
}
... @defer {
cart {
id
total
items {
id
quantity
price
}
}
}
}
With this:
- One request is sent
- Multiple responses are streamed back over time
- Your UI can progressively render each section
Important:
- Your server must support
@deferfor this to work - Not all GraphQL servers support it out of the box
Again, if you’re using Apollo Client / Apollo Server, they provide support for @defer (with proper configuration).
Fragment colocation (highly recommended)
When working with big queries, a really good pattern is fragment colocation:
- Each component defines its own fragment
- The main query just composes those fragments
This keeps your code modular, scalable, and easier to maintain as your app grows.
Good reference:
That article uses GraphQL Code Generator, but it’s worth noting:
- Apollo Client already supports fragments and data masking out of the box
- You don’t necessarily need to use
useFragmentfrom codegen - And under the hood,
useFragmentisn’t really a hook anyway
This post explains the discussion about Apollo and Codegen regarding fragments: