Using Modern Directives (defer, stream)
1. Understanding @defer Directive
| Aspect | Detail |
|---|---|
| Status | Incremental Delivery EXPERIMENTAL |
| Effect | Server returns initial payload, then patches for deferred fragments |
| Transport | multipart/mixed HTTP response |
| Args | label: String, if: Boolean |
2. Using @defer for Slow Fields
Example: Defer slow nested data
query Profile {
user(id: "1") {
id
name
... @defer(label: "stats") {
activityStats { posts comments likes }
}
}
}
3. Understanding @stream Directive
| Arg | Detail |
|---|---|
| initialCount | How many items in first payload |
| label | Identify the patch |
| if | Conditional streaming |
4. Using @stream for Large Lists
Example: Stream comments
query Feed {
posts {
id
title
comments @stream(initialCount: 5) {
id
body
}
}
}
5. Implementing Incremental Delivery
| Server | Support |
|---|---|
| graphql-yoga | Built-in |
| graphql-helix | Built-in |
| Apollo Server 4 | Behind flag EXPERIMENTAL |
| graphql-js | experimentalExecuteIncrementally |
6. Handling Deferred Responses
Example: Initial then incremental payloads
// First payload
{ "data": { "user": { "id": "1", "name": "Ada" } }, "hasNext": true }
// Subsequent
{ "incremental": [{ "path": ["user"], "data": { "activityStats": { ... } } }], "hasNext": false }
7. Handling Streamed Responses
| Payload Field | Meaning |
|---|---|
| items | New list elements |
| path | Where to merge in original response |
| hasNext | true while more chunks coming |
8. Combining @defer and @stream
Example: Defer fragment containing streamed list
query Dashboard {
... @defer {
feed {
items @stream(initialCount: 3) { id title }
}
}
}
9. Understanding Browser Support
| Client | Support |
|---|---|
| Apollo Client 3.7+ | Yes — multipart subscription transport |
| Relay 14+ | Yes — native @defer/@stream |
| urql | Limited via @urql/exchange-multipart-fetch |
| Browsers | Need fetch + ReadableStream (modern only) |