Shrink GraphQL Requests with Automatic Persisted Queries
Send query hashes instead of full GraphQL documents on repeat requests to save bandwidth and improve cache hits.
17 Aug 2026, 16:28 UTC

Repeat GraphQL queries send more data than necessary
Every time a client executes a GraphQL operation, it usually posts the full query document: operation name, selected fields, fragments, and directives. If the same dashboard loads hundreds of times, those bytes repeat on every request. Mobile users pay for the traffic, and intermediate caches struggle because the request body is rarely identical from one load to the next.
Automatic Persisted Queries (APQ) address this by letting the client send a short cryptographic hash instead of the full document after the first exchange. A cryptographic hash is a fixed-length fingerprint of data. Serialized means converted to a consistent string format; APQ hashes that serialized form so the server can identify the query without receiving the query text itself.
How the two-step handshake works
APQ works in two steps. First, the client hashes the serialized query document and sends only that hash plus any variables. If the server recognizes the hash, it looks up the stored document and executes the operation. If the hash is unknown, the server signals a miss, and the client retries with the complete query body. The server then stores the hash-to-document mapping so future requests can use the short form.
Major clients and servers support APQ, including Apollo Client, Apollo Server, GraphQL Yoga, and urql. Exact header names, hash algorithms, and document serialization rules differ between implementations, so a client configured for one server may not interoperate with another without adjustment.
Worked example: client setup and what to verify
This example uses Apollo Client in a browser-based frontend. Package names and APIs vary by version, so treat the code as a pattern, not a copy-and-paste guarantee.
Generate a hash locally
You can compute the same kind of fingerprint your client will send. Run this in a local terminal; no special permissions are required.
# Run in your local development terminal.
# printf avoids the trailing newline that echo adds, which would change the hash.
printf '%s' 'query { user { id name } }' | sha256sum
Expected check: a 64-character hexadecimal string. Risk: adding whitespace, comments, or a trailing newline to the input produces a different hash, which will cause a cache miss.
Configure the client
import { createPersistedQueryLink } from '@apollo/client/link/persisted-queries';
import { createHttpLink } from '@apollo/client';
import { ApolloClient, InMemoryCache } from '@apollo/client';
const httpLink = createHttpLink({
uri: 'https://api.example.com/graphql',
});
const client = new ApolloClient({
link: createPersistedQueryLink().concat(httpLink),
cache: new InMemoryCache(),
});
Replace https://api.example.com/graphql with your endpoint. Run this in your frontend build environment; standard npm permissions apply. The link handles hashing internally, but confirm your server expects the same hash algorithm and header.
Verify in the browser
- Open Developer Tools and select the Network tab.
- Load a page that executes a GraphQL operation.
- Inspect the first request: the body should include the full
querystring. - Execute the same operation again. The body should contain only a hash identifier and variables.
- Alter whitespace or comments in the query without changing its meaning. The hash should change, and the server should fall back to the full document.
If step five does not produce a full-document retry, your client and server likely disagree on how the document is serialized before hashing.
Trade-offs and limitations
- No savings on cold requests. The first transmission of a new or changed query still sends the complete document. Benefits appear on repetition.
- Harder server-side debugging. Logs may show only hashes instead of readable queries. Maintain a hash-to-document registry or enable detailed logging for incident response.
- Registry growth. Applications with many client-generated operations can accumulate a large mapping store. Plan for cleanup or size limits.
- Not a substitute for access control. A valid hash can still resolve to an expensive or sensitive operation. Keep depth limits, complexity analysis, authorization, and rate limiting.
Rollback
Enabling APQ changes client and server behavior. To roll back, remove the persisted-query link from the client and any server-side persisted-query integration, then redeploy. Because the server still accepts full documents, older clients continue to work during the transition.
Check the result after deployment
Compare average request-body size in your CDN or server logs before and after enabling APQ. You should see smaller bodies for repeat operations and no increase in errors for unchanged queries. If errors rise, investigate hash mismatches causing unnecessary full-document retries.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.