Skip to content

iOS Normalized Cache: Detail Query Cache Miss When Object Exists (Missing QUERY_ROOT.review(encid:) Entry) #3620

@ferrufino

Description

@ferrufino

Question

Hello team,
I'm using Apollo iOS 1.18.0 with normalized caching and encountered a frustrating issue:

  1. User loads a paginated list (e.g., business reviews)
  2. Review objects get cached correctly with normalized keys (Review:)
  3. User taps a review to see details
  4. Cache miss occurs, triggering an unnecessary network request (even though the data already exists in the cache!)

Example Scenario

Query 1 - Paginated List:
query GetBusinessReviews($encid: String!, $first: Int, $after: String) { business(encid: $encid) { reviews(first: $first, after: $after) { edges { node { encid rating text { full } business { encid, alias } } } pageInfo { hasNextPage, endCursor } } } }

Query 2 - Detail Screen:
query GetReview($encid: String!) { review(encid: $encid) { encid rating text { full } business { encid, alias } } }

Root Cause

Apollo's cache stores data in two layers:

  1. QUERY_ROOT entries (entry points for queries)
  2. Normalized objects (the actual data, keyed by ID)

What Query 1 creates:
QUERY_ROOT.business(encid:X) → Business:X
Review:ABC (normalized) ✅

What Query 2 looks for:
QUERY_ROOT.review(encid:ABC) ❌ (doesn't exist!)

Even though Review:ABC exists as a normalized object, Apollo can't use it because the query root entry doesn't exist. Apollo always starts resolution from QUERY_ROOT.

I’m aware of withinReadTransaction, but relying on manual record reads feels like a workaround: it bypasses GraphQL selection-set decoding and increases the risk of drift/bugs as the schema evolves.

Questions:

  1. Is there a better way to create QUERY_ROOT entries programmatically without manual cache writes?
  2. Has anyone else solved this differently?
  3. Will Apollo iOS 2.x have improvements for cross-query cache resolution?

I didn't know if this fit as a feature request or a bug so decided to tag it as a question.

Metadata

Metadata

Assignees

No one assigned

    Labels

    questionIssues that have a question which should be addressed

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions