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 } }
}

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.