Skip to content

Commit 1eb6e3f

Browse files
martinbonninBoDMeschreiber
authored
Update persisted queries doc (#5165)
* update PQs doc * update * update * update * update * update * update * Update docs/source/advanced/persisted-queries.mdx Co-authored-by: Benoit Lubek <[email protected]> * Update docs/source/advanced/persisted-queries.mdx Co-authored-by: Benoit Lubek <[email protected]> * Copy edit and use shared component where useful * Move nav placement * Use <ClientPQImplementation> component * Align to other client docs language * Fix header * Align headers --------- Co-authored-by: Benoit Lubek <[email protected]> Co-authored-by: Maria Elisabeth Schreiber <[email protected]>
1 parent bbe557b commit 1eb6e3f

File tree

2 files changed

+80
-36
lines changed

2 files changed

+80
-36
lines changed
Lines changed: 78 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,102 @@
11
---
2-
title: Persisted queries in Apollo Kotlin
2+
title: Persisted queries
3+
description: Secure your graph while minimizing request latency
34
---
45

5-
## Automatic persisted queries
6+
<ClientPQIntro />
67

7-
Apollo Kotlin supports [Automatic Persisted Queries](https://www.apollographql.com/docs/apollo-server/performance/apq/) (APQ). To take advantage of it, your GraphQL server _also_ needs to support APQ (Apollo Server supports it out of the box).
8+
Hashed queries are also sent by default using HTTP `GET` instead of the default `POST`, making them easier to cache in your edge network.
89

9-
Enable the feature when you initialize your `ApolloClient` instance, like so:
10+
## Differences between persisted queries and APQs
11+
12+
<ClientPQDifferences />
13+
14+
## Implementation steps
15+
16+
Both persisted queries and APQs require you to configure how your client makes requests. If you intend to use persisted queries for safelisting, you also need to generate and publish an operation manifest.
17+
18+
<ClientPQImplementation />
19+
20+
### 0. Requirements
21+
22+
You can use APQs with the following versions of Apollo Kotlin, Apollo Server, and Apollo Router:
23+
- Apollo Kotlin (v1.0.0+)
24+
- [Apollo Server](/apollo-server/) (v1.0.0+)
25+
- [Apollo Router](/router) (v0.1.0+)
26+
27+
> **Note:** You can use _either_ Apollo Server _or_ Apollo Router for APQs. They don't need to be used together.
28+
29+
Persisted queries is currently in [preview](/resources/product-launch-stages#preview) and has the following requirements:
30+
- Apollo Kotlin (v3.8.2+)
31+
- [Apollo Router](/router) (v1.25.0+)
32+
- [GraphOS Enterprise plan](/graphos/enterprise/)
33+
34+
### 1. Generate operation manifest
35+
36+
> This step is only required for implementing safelisting with persisted queries. It is _not_ required for APQs.
37+
38+
The operation manifest acts as a safelist of trusted operations the [Apollo Router](/router/) can check incoming requests against.
39+
To generate the operation manifest, set `operationManifestFormat` to `"persistedQueryManifest"` in your Gradle script:
1040

1141
```kotlin
12-
val apolloClient = ApolloClient.Builder()
13-
.serverUrl("https://...")
14-
.autoPersistedQueries()
15-
.build()
42+
// build.gradle.kts
43+
apollo {
44+
service("api") {
45+
packageName.set("com.example")
46+
47+
// Enable generation of the operation manifest
48+
operationManifestFormat.set("persistedQueryManifest") // highlight-line
49+
}
50+
}
1651
```
1752

18-
You can optionally configure the HTTP methods to use. Using `GET` may take advantage of HTTP caching for instance when using a CDN:
19-
```kotlin
20-
val apolloClient = ApolloClient.Builder()
21-
.serverUrl("https://...")
22-
.autoPersistedQueries(
23-
// For the initial hashed query that does not send the actual Graphql document
24-
httpMethodForHashedQueries = HttpMethod.Get,
25-
26-
// For the follow-up query that sends the full document if the initial hashed query was not found
27-
httpMethodForDocumentQueries = HttpMethod.Get
28-
)
29-
.build()
53+
The operation manifest is generated during code generation. This happens automatically every time you build your project or you can trigger it manually by executing the `generateApolloSources` Gradle task.
54+
55+
The operation manifest is generated in `build/generated/manifest/apollo/$serviceName/persistedQueryManifest.json`, where `$serviceName` is `"api"` here. The resulting operation manifest looks something like this:
56+
57+
```json title="persistedQueryManifest.json"
58+
{
59+
"format": "apollo-persisted-query-manifest",
60+
"version": 1,
61+
"operations": [
62+
{
63+
"id": "e0321f6b438bb42c022f633d38c19549dea9a2d55c908f64c5c6cb8403442fef",
64+
"body": "query GetItem { thing { __typename } }",
65+
"name": "GetItem",
66+
"type": "query"
67+
}
68+
]
69+
}
3070
```
3171

32-
Note that mutations will always be sent as `POST` requests, regardless of these settings, as to avoid hitting caches.
72+
### 2. Publish operation manifest
3373

34-
## Disable persisted queries for certain queries
74+
> This step is only required for implementing safelisting with persisted queries. It is _not_ required for APQs.
75+
76+
<PublishPQMs />
77+
78+
### 3. Enable persisted queries on `ApolloClient`
79+
80+
Once you've configured your code generation to include operation IDs, you can update your client to query by operation ID rather than the full operation string. This configuration is the same whether you're using APQs or persisted queries. Call `autoPersistedQueries()` on your `ApolloClient.Builder`:
3581

36-
You may want to disable persisted queries for certain queries, for instance to avoid any caching when the data is updated often. In order to do that, set `enableAutoPersistedQueries` to false on the `ApolloCall`:
3782
```kotlin
38-
apolloClient.query(myQuery).enableAutoPersistedQueries(false).toFlow()
83+
val apolloClient = ApolloClient.Builder()
84+
.serverUrl("https://...")
85+
.autoPersistedQueries()
86+
.build()
3987
```
4088

41-
## operationOutput.json
89+
Once APQs are enabled on your ApolloClient, hashed queries are sent by default.
4290

43-
If your backend uses custom persisted queries, Apollo Kotlin can generate an OperationOutput json from your .graphql queries. They will match what the client is sending exactly so you can persist them on your server.
91+
You may want to disable automatic persisted queries for certain queries, for instance to avoid any caching when the data is updated often. To do that, set `enableAutoPersistedQueries` to false on the `ApolloCall`:
4492

4593
```kotlin
46-
apollo {
47-
service("service") {
48-
generateOperationOutput.set(true)
49-
}
50-
}
94+
apolloClient.query(myQuery).enableAutoPersistedQueries(false).toFlow()
5195
```
5296

53-
## Custom ID for Persisted Queries
97+
## Generating custom IDs for persisted queries
5498

55-
By default, Apollo uses `Sha256` hashing algorithm to generate an ID for the query. To provide custom ID generation logic, use the option - `operationIdGenerator` which accepts an `instance` that implements the `OperationIdGenerator` interface (`com.apollographql.apollo3.compiler.OperationIdGenerator`) as the input. This option can be used to either specify a different hashing algorithm or to fetch the persisted query ID from a different place - e.g. a service or a CLI.
99+
By default, Apollo uses `Sha256` hashing algorithm to generate an ID for the query. To provide custom ID generation logic, use the `operationIdGenerator` option. It accepts an `instance` that implements the `OperationIdGenerator` interface (`com.apollographql.apollo3.compiler.OperationIdGenerator`) as the input. You can use this option to either specify a different hashing algorithm or to fetch the persisted query ID from a different location, for example, from a service or a CLI.
56100

57101
Example Md5 hash generator:
58102

@@ -94,6 +138,6 @@ apollo {
94138

95139
</MultiCodeBlock>
96140

97-
### Versioning Id Generator
141+
### ID generator versioning
98142

99143
The result of the ID generator is cached. The cache is not updated when the implementation of the ID Generator changes. To indicate an update to the implementation of the ID Generator, change the `version` override as shown in the above example.

docs/source/config.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@
3939
"Error handling": "/essentials/errors",
4040
"Custom scalars": "/essentials/custom-scalars",
4141
"Fragments": "/essentials/fragments",
42-
"@defer support (experimental)": "/fetching/defer"
42+
"@defer support (experimental)": "/fetching/defer",
43+
"Persisted queries": "/advanced/persisted-queries"
4344
},
4445
"Caching": {
4546
"Introduction": "/caching/introduction",
@@ -49,7 +50,6 @@
4950
"Watching cached data": "/caching/query-watchers",
5051
"ApolloStore": "/caching/store",
5152
"HTTP cache": "/caching/http-cache",
52-
"Persisted queries": "/advanced/persisted-queries",
5353
"Troubleshooting": "/caching/troubleshooting"
5454
},
5555
"Networking": {

0 commit comments

Comments
 (0)