Skip to content

Commit 6f7fa7b

Browse files
committed
Split content onto separate caching and performance pages.
1 parent 7533488 commit 6f7fa7b

File tree

4 files changed

+59
-55
lines changed

4 files changed

+59
-55
lines changed

src/pages/learn/_meta.ts

+1
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,6 @@ export default {
1919
authorization: "",
2020
pagination: "",
2121
"global-object-identification": "",
22+
caching: "",
2223
performance: "",
2324
}

src/pages/learn/caching.mdx

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# Caching
2+
3+
<p className="learn-subtitle">Provide Object Identifiers so clients can build rich caches</p>
4+
5+
In an endpoint-based API, clients can use [HTTP caching](https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching) to avoid refetching resources and to identify when two resources are the same. The URL in these APIs is a _globally unique identifier_ that the client can leverage to build a cache.
6+
7+
In GraphQL, there's no URL-like primitive that provides this globally unique identifier for a given object. Hence, it's a best practice for the API to expose such an identifier for clients to use as a prerequisite for certain types of caching.
8+
9+
## Globally unique IDs
10+
11+
### Standardize how objects are identified in a schema
12+
13+
One possible pattern for this is reserving a field, like `id`, to be a globally unique identifier. The example schema used throughout these docs uses this approach:
14+
15+
```graphql
16+
# { "graphiql": true }
17+
query {
18+
starship(id: "3003") {
19+
id
20+
name
21+
}
22+
droid(id: "2001") {
23+
id
24+
name
25+
friends {
26+
id
27+
name
28+
}
29+
}
30+
}
31+
```
32+
33+
This is a powerful tool for client developers. In the same way that the URLs of a resource-based API provide a globally unique key, the `id` field in this system provides a globally unique key.
34+
35+
If the backend uses something like UUIDs for identifiers, then exposing this globally unique ID may be very straightforward! If the backend doesn't have a globally unique ID for every object already, the GraphQL layer might have to construct one. Oftentimes, that's as simple as appending the name of the type to the ID and using that as the identifier. The server might then make that ID opaque by base64-encoding it.
36+
37+
Optionally, this ID can then be used to work with the `node` pattern when using [global object identification](/learn/global-object-identification).
38+
39+
### Compatibility with existing APIs
40+
41+
One concern with using the `id` field for this purpose is how a client using the GraphQL API would work with existing APIs. For example, if our existing API accepted a type-specific ID, but our GraphQL API uses globally unique IDs, then using both at once can be tricky.
42+
43+
In these cases, the GraphQL API can expose the previous API's IDs in a separate field. This gives us the best of both worlds:
44+
45+
- GraphQL clients can continue to rely on a consistent mechanism to get a globally unique ID.
46+
- Clients that need to work with our previous API can also fetch `previousApiId` from the object, and use that.
47+
48+
### Alternatives
49+
50+
While globally unique IDs have proven to be a powerful pattern in the past, they are not the only pattern that can be used, nor are they right for every situation. The critical functionality that the client needs is the ability to derive a globally unique identifier for their caching. While having the server derive that ID simplifies the client, the client can also derive the identifier. This could be as simple as combining the type of the object (queried with `__typename`) with some type-unique identifier.
51+
52+
Additionally, if replacing an existing API with a GraphQL API, then it may be confusing if all of the fields in GraphQL are the same **except** `id`, which changed to be globally unique. This would be another reason why one might choose not to use `id` as the globally unique field.
53+
54+
## Recap
55+
56+
To recap these recommendations for using caching with GraphQL APIs:
57+
58+
- Defining a globally unique ID field for an Object type can facilitate various types of caching

src/pages/learn/performance.mdx

-50
Original file line numberDiff line numberDiff line change
@@ -8,55 +8,6 @@ In practice, however, GraphQL is as cacheable as any API that enables parameteri
88

99
On this page, we'll explore several different tactics that can be leveraged in GraphQL clients and servers to optimize how data is fetched from the API.
1010

11-
## Globally unique IDs
12-
13-
In an endpoint-based API, clients can use [HTTP caching](https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching) to avoid refetching resources and to identify when two resources are the same. The URL in these APIs is a _globally unique identifier_ that the client can leverage to build a cache.
14-
15-
In GraphQL, there's no URL-like primitive that provides this globally unique identifier for a given object. Hence, it's a best practice for the API to expose such an identifier for clients to use as a prerequisite for certain types of caching.
16-
17-
### Standardize how objects are identified in a schema
18-
19-
One possible pattern for this is reserving a field, like `id`, to be a globally unique identifier. The example schema used throughout these docs uses this approach:
20-
21-
```graphql
22-
# { "graphiql": true }
23-
query {
24-
starship(id: "3003") {
25-
id
26-
name
27-
}
28-
droid(id: "2001") {
29-
id
30-
name
31-
friends {
32-
id
33-
name
34-
}
35-
}
36-
}
37-
```
38-
39-
This is a powerful tool for client developers. In the same way that the URLs of a resource-based API provide a globally unique key, the `id` field in this system provides a globally unique key.
40-
41-
If the backend uses something like UUIDs for identifiers, then exposing this globally unique ID may be very straightforward! If the backend doesn't have a globally unique ID for every object already, the GraphQL layer might have to construct one. Oftentimes, that's as simple as appending the name of the type to the ID and using that as the identifier. The server might then make that ID opaque by base64-encoding it.
42-
43-
Optionally, this ID can then be used to work with the `node` pattern when using [global object identification](/learn/global-object-identification).
44-
45-
### Compatibility with existing APIs
46-
47-
One concern with using the `id` field for this purpose is how a client using the GraphQL API would work with existing APIs. For example, if our existing API accepted a type-specific ID, but our GraphQL API uses globally unique IDs, then using both at once can be tricky.
48-
49-
In these cases, the GraphQL API can expose the previous API's IDs in a separate field. This gives us the best of both worlds:
50-
51-
- GraphQL clients can continue to rely on a consistent mechanism to get a globally unique ID.
52-
- Clients that need to work with our previous API can also fetch `previousApiId` from the object, and use that.
53-
54-
### Alternatives
55-
56-
While globally unique IDs have proven to be a powerful pattern in the past, they are not the only pattern that can be used, nor are they right for every situation. The critical functionality that the client needs is the ability to derive a globally unique identifier for their caching. While having the server derive that ID simplifies the client, the client can also derive the identifier. This could be as simple as combining the type of the object (queried with `__typename`) with some type-unique identifier.
57-
58-
Additionally, if replacing an existing API with a GraphQL API, then it may be confusing if all of the fields in GraphQL are the same **except** `id`, which changed to be globally unique. This would be another reason why one might choose not to use `id` as the globally unique field.
59-
6011
## `GET` requests for queries
6112

6213
GraphQL implementations that adhere to the [GraphQL over HTTP specification](https://github.com/graphql/graphql-over-http/blob/main/spec/GraphQLOverHTTP.md) will support the `POST` HTTP method by default, but may also support `GET` requests for query operations.
@@ -119,7 +70,6 @@ Observability tooling can provide insight into where bottlenecks exist in the ex
11970

12071
To recap these recommendations for improving GraphQL API performance:
12172

122-
- Defining a globally unique ID field for an Object type can facilitate various types of caching
12373
- Using `GET` for GraphQL query operations can support HTTP caching and CDN usage, particularly when used in conjunction with hashed query documents
12474
- Because an operation's selection set can express relationships between different kinds of objects, the N+1 problem can be mitigated during field execution by batching and caching requests to underlying data sources
12575
- Field pagination, limiting operation depth and breadth, and rate-limiting API requests can help prevent individual GraphQL operations from placing excessive load on server resources

vercel.json

-5
Original file line numberDiff line numberDiff line change
@@ -110,11 +110,6 @@
110110
"destination": "/learn/validation/",
111111
"permanent": true
112112
},
113-
{
114-
"source": "/learn/caching/",
115-
"destination": "/learn/performance/",
116-
"permanent": true
117-
},
118113
{
119114
"source": "/docs/videos",
120115
"destination": "/community/#videos/",

0 commit comments

Comments
 (0)