Lesson 6 of 30
Deciding whether a mutation should invalidate-and-refetch or write directly into the cache is a real code-level choice with a real correctness tradeoff, not a detail a library hides from you.
14 min read
Every option explains itself — why the right one is right, and why each wrong one is wrong. Miss one and it comes back later on a spaced-repetition schedule.
Question 1 of 3
A mutation to like a post returns `{ success: true }` with no other data. Which cache-update strategy is actually safe to use here?
Hints without spoilers, and a plain explanation of why a wrong answer was wrong — answered only from this lesson. Free account, no card.
Sign up freeWhat interviewers actually ask about this, and what a strong answer has to cover.
A strong answer covers
Likely follow-ups
Once data is cached client-side, a mutation (a POST/PATCH/DELETE that changes something on the server) leaves the cache holding a value that's now wrong. Something has to reconcile the two, and there are exactly two concrete ways to actually write that code:
Neither one is "the right one" in general. Invalidate-and-refetch is the safe default; direct cache write is the optimization you reach for on a mutation that's hot enough, or latency-sensitive enough, to justify hand-writing the update.
Both approaches acting on the same mutation, a POST /posts/:id/like that returns the post's new like count:
// Approach 1: invalidate-and-refetch
async function likePost(postId: string) {
await api.post(`/posts/${postId}/like`);
// Mark this key stale; the cache layer refetches it (and any
// other query currently reading the same key) on its own schedule.
cache.invalidate(["post", postId]);
}
// Approach 2: direct cache write
async function likePost(postId: string) {
const res = await api.post<{ likeCount: number }>(`/posts/${postId}/like`);
// No refetch — trust the response and write the new value ourselves.
cache.setQueryData(["post", postId], (old) => ({
...old,
likeCount: res.likeCount,
}));
}
A user likes a post. The mutation request fires and the server processes it.
The second version only works because the response actually contains likeCount. If the endpoint just returned { success: true }, a direct write would have nothing correct to write, and reaching for likeCount: likeCount + 1 off stale local state is exactly how the cache and the server quietly drift apart — that increment is only right if no other tab, device, or user changed the count in between.
"After this mutation succeeds, how does the UI actually end up showing the new data?" is a real follow-up to any caching discussion, and naming both strategies — plus the specific tradeoff between them — shows you've actually written this code, not just read about caching in the abstract.