Lesson 14 of 30
A nested API response duplicates the same embedded object everywhere it appears — normalizing it into a flat by-id lookup means one update reflects everywhere that data is used, automatically.
13 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
Ten blog posts in a nested API response each embed the same author's full object inline. The author changes their display name. What's the real problem this creates in a client that stored the response as-is?
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
A typical nested API response embeds related data inline. A list of blog posts, each with its full author object copied inline, is a common shape — and a real problem: if ten posts were written by the same author, that author's name, avatar, and bio are duplicated ten separate times in the response. If that author later changes their display name, every one of those ten independently-stored copies needs updating separately, or the UI shows a different name for the same person depending on which post happens to be on screen.
Normalization is the concrete fix: walk the nested response once and restructure it into a flat lookup, organized by entity type and id — something like { posts: { byId: {...}, allIds: [...] }, authors: { byId: {...} } }. Each post keeps only the author's id, not the full embedded object. Reading a post's author back out means looking it up by that id in the authors table. Because every post referencing the same author id points at the exact same single stored record, updating that one record makes every post referencing it correct automatically — there's nothing else to update, because nothing else was ever storing its own separate copy.
// Raw nested response — the same author object duplicated per post
const raw = {
posts: [
{ id: "p1", title: "Intro to caching", author: { id: "a1", name: "Priya Shah" } },
{ id: "p2", title: "Cache invalidation", author: { id: "a1", name: "Priya Shah" } },
],
};
// Normalized: entities flattened into by-id tables, posts reference authors by id only
function normalize(data: typeof raw) {
const authorsById: Record<string, { id: string; name: string }> = {};
const postsById: Record<string, { id: string; title: string; authorId: string }> = {};
for (const post of data.posts) {
authorsById[post.author.id] = post.author;
postsById[post.id] = { id: post.id, title: post.title, authorId: post.author.id };
}
return { posts: { byId: postsById, allIds: data.posts.map((p) => p.id) }, authors: { byId: authorsById } };
}
Two posts, each embedding its own full copy of the same author object — duplicated data.
Rendering a post now needs a small join step instead of one direct read: authors.byId[posts.byId[postId].authorId]. That's the real cost — denormalized data reads back out in one step; normalized data needs a lookup. What it buys back: updating authors.byId["a1"].name once updates the name everywhere a1 is referenced, because every reference points at that same single record instead of an independent copy.
allIds alongside byId isn't optional decoration. A plain object's key order isn't a reliable source of display order, so a normalized list still needs an explicit array of ids to know what order to render in."How would you structure client-side state for a list of posts, each with an author, so that an author update stays consistent everywhere?" is a real question that tests whether a candidate reaches for normalization deliberately, with a clear account of what it costs at read time, rather than either not knowing the pattern or applying it reflexively everywhere.