Photo by Eric Er on Unsplash

On this page

This chapter follows Managing GraphQL schemas in organizations.

Backend teams often learn these pitfalls in production. Each section follows symptom → cause → fix.

Nullability changes break clients differently

Symptom: Web clients crash on null where they expected strings; mobile apps on old schema still send old queries.

Cause: Adding ! to an output field turns previous null responses into GraphQL errors that bubble. Making an input field required breaks operations that omitted it.

Fix: Add new fields instead of tightening nullability; use deprecation. For inputs, add a new optional field or a new input type version.

Required arguments and input fields

Symptom: Deploy succeeds; clients receive validation errors Argument "X" of required type.

Cause: New required argument on a field or new required input property.

Fix: Default the argument in schema or keep it optional until telemetry shows all operations updated.

New enum values and exhaustive switches

Symptom: TypeScript switch throws on unknown enum; UI shows blank state.

Cause: Client generated exhaustive enums; server added a value.

Fix: Treat enums as open sets in UI (default branch); regenerate types. Document enum additions in changelog.

Stale client cache metadata

Symptom: Union fragments stop rendering after deploy though queries succeed.

Cause: Apollo possibleTypes or Graphcache schema JSON missing new implementors.

Fix: Ship client updates with refreshed introspection artifacts in the same release as schema changes.

Persisted query hash mismatches

Symptom: Gateway returns PersistedQueryNotFound or rejects operations.

Cause: Field removed from schema but mobile app still sends old persisted hash.

Fix: Version persisted query sets; support dual hashes during migration; avoid removing fields until usage clears.

Long tail of mobile versions

Symptom: Crash reports reference removed fields weeks after backend cleanup.

Cause: App store review delays; users on old binaries.

Fix: Longer deprecation windows for mobile; feature flags on client to stop selecting fields before backend removal.

Semantic changes without schema diffs

Symptom: Finance reports wrong totals; schema validation passes.

Cause: Resolver now computes total with tax included—same field name, different meaning.

Fix: Add totalWithTax or bump documented API behavior; treat as breaking in comms even if SDL unchanged.

Changing ID format

Symptom: Normalized caches show duplicates; links break.

Cause: Switched from numeric IDs to UUIDs without client cache eviction.

Fix: Treat as breaking; bump cache key prefix or force app refresh.

Deploy order in federation

Symptom: Router fails composition or queries error on @requires fields.

Cause: Subgraph B deployed before subgraph A exposing new @external field.

Fix: Compose in CI; use composition checks; deploy router-compatible subgraph sets together.

Federation composition breaks

Symptom: CI blocks publish: entity key conflict or interface mismatch.

Cause: Two teams defined @key differently on shared entity.

Fix: Align entity ownership; use schema checks in registry; document key fields in guild meetings.

Next: Securing GraphQL APIs.

Search articles

Type a word to search published articles.

Open the search page