Mobile API Best Practices · Versioning, Upgrades & Remote Control
GraphQL & Persisted Operations for Mobile
Client-selected shapes with safe, cacheable, versioned operations.
GraphQL suits mobile: one round trip, exactly the fields a screen needs, typed codegen (Apollo Kotlin/iOS). In production, use persisted (trusted) operations: the build registers each query and the app sends its ID/hash instead of the text — smaller requests, GET-cacheable, and the server can reject arbitrary queries. Since old app versions keep their operations forever, never remove fields they use; deprecate with @deprecated and track field usage per client version.
Operation delivery modes
| Criterion | Ad-hoc queries | Automatic persisted queries (APQ) | Trusted documents (allowlist) |
|---|---|---|---|
| Request size | Full query | Hash (query sent once on miss) | ID only |
| Arbitrary queries allowed | Yes | Yes | No |
| CDN cacheable (GET) | Hard | Yes | Yes |
| Security posture | Needs depth/complexity limits | Same | Strong |
| Build integration | None | Runtime | Register at build time |
query HomeScreen($first: Int!) {
viewer { id displayName avatar(size: 96) { url } }
feed(first: $first) { edges { node { id title thumbnail(width: 320) { url } } } pageInfo { endCursor hasNextPage } }
}
GET /graphql?doc_id=sha256:4f1b…&variables=%7B%22first%22%3A20%7D
apollographql-client-name: ios
apollographql-client-version: 5.12.0
Common pitfalls
- Removing a deprecated field still used by old app versions.
- Allowing arbitrary queries from public clients without limits.
- N+1 resolvers behind a screen query.
Key points
- Persisted/trusted operations in production
- Field usage telemetry per client version
- Deprecate, don't delete
Further reading: Apollo: Persisted queries
Practice questions
What are trusted documents (persisted operations)?
Answer
Operations registered at build time; clients send only an ID and the server executes only known documents, improving size, caching and security.
How do you know when a GraphQL field can be removed?
Answer
Track field usage by client name/version; remove only after no supported client version requests it.
Open in the app to mark lessons complete, take notes and track your progress.