What a mutation or subscription response needs so the frontend cache updates without a refetch, and how to ask for a change
id and the fields that changed, Apollo merges it into the cache and every component that shows it updates, with no extra request. When the response leaves that out, the frontend has to guess with cache.modify or refetch a query, and a refetch puts every component that reads the query into a refetching state.
This page is for developers porting code that reuses the existing Prepared911 data. The schema comes from the graphql-ruby types in the Prepared911 repository, composed by AxonMundi and vendored here as packages/data-gql/src/schema.graphql. You can't fix a response shape from this repository, but you can ask for it.
id and changed fields, and the parent that owns a list or count it changed. A delete returns the deleted id (and the parent). ok: true is enough only when no cached object changed.id: ID!. It stays the same for the life of the record and whichever operation returns it, so a chatroom from a list, a subscription and a mutation all land on one cache entry. A type without an id is stored inside its parent and can't be shared between queries.CREATED, UPDATED, REMOVED) or a separate event per kind, so the client knows whether to add it to a list, update it, or drop it. Prefer an enum to a string. A subscription that only says "something changed" makes every subscriber refetch.chatroomLock returns { id, locked } on its own payload type, so Chatroom.locked stays stale everywhere until something refetches it. chatroomBookmarkDelete is the pattern to copy: it returns the deleted id and the parent chatroom.
Apollo recommends the same shape in Include modified objects in mutation responses.
If an operation forces a refetchQueries, a refetch from a subscription handler, or a cache.modify that only exists because the payload is missing data, consider asking the backend to improve its shape. Port the operation with the workaround first, so the port isn't blocked, and say in a comment which request would remove it. See Mutation order for the workaround and Freshness and Loading States for how a refetch affects other components.
Work through this before you write the request:
schema.graphql. If each changed entity is reachable from the payload, directly or through a back-reference such as chatroomAnalysis.chatroom, select it: you don't need the backend.id: ID!, or is it only keyed by cache-key-fields.json?refetchQueries, cache.modify, polling) and what it costs (a refetch on every component that reads the query, a skeleton flash, an extra request).chatroomLock and chatroomUnlock return ChatroomLockPayload { chatroom, id, locked } (schema.graphql:10694). The chatroom field is deprecated with "Use id and locked instead", and id and locked sit on the payload, so Apollo stores them as a ChatroomLockPayload record and Chatroom.locked never changes.
locked onto the chatroom with cache.modify after the mutation, or refetch the chatroom queries. Both exist only because of the payload.chatroom and drop its deprecation, so a document selects chatroom { id locked } and every component that shows the chatroom updates on its own.