Choosing a Data-Fetching Strategy for a New Feature
The individual topics in this track aren't independent trivia — they're a checklist a working frontend developer actually runs, consciously or not, every time a new feature needs to talk to a backend.
13 min read
Check your understanding
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 new dashboard panel only needs to be fresh whenever the user opens the page — it never needs to update while the page sits open. Which fetching strategy fits?
Stuck? Ask the AI tutor
Hints without spoilers, and a plain explanation of why a wrong answer was wrong — answered only from this lesson. Free account, no card.
Interview questions on Choosing a Data-Fetching Strategy for a New Feature
What interviewers actually ask about this, and what a strong answer has to cover.
You're asked to build a 'recent activity' panel for a dashboard. Walk me through the sequence of data-fetching decisions you'd actually make before writing code.
A strong answer covers
Asks how time-sensitive the data needs to be and chooses between a one-time fetch, polling, or a real-time push channel based on that, not by default
Considers whether the endpoint needs runtime schema validation, based on whether it's an independently-versioned/external service or a tightly-coupled internal one
Considers whether the activity data needs normalizing, based on whether the same underlying records render in more than one place on the page
Explicitly designs the loading, empty, and error states for this specific feature rather than treating them as an afterthought
Likely follow-ups
How would your answer change if this same panel needed to show a teammate's action the instant they took it, without a page refresh?
Which of these four decisions would you reconsider first if you learned partway through that this endpoint is maintained by a separate team on its own release schedule?
Picture a real, ordinary feature request: add a "recent activity" panel to a dashboard, showing the last handful of things that happened in an account. Nothing about that request answers the actual implementation questions — those come from running through a real sequence of decisions, each one pulling in something this track already covered.
How time-sensitive is this data, really? If "recent activity" only needs to be fresh whenever the user opens the page, a one-time fetch on mount is enough. If it should update while the page sits open, that's polling — a fetch on an interval. If it genuinely needs to reflect activity the instant it happens (someone else on the team just did something, and it should appear without a refresh), that's a real-time push channel. This is exactly the decision covered by the earlier lessons on choosing between polling and a real-time push connection — the "recent activity" feature is a textbook case for actually asking the question instead of defaulting to whichever one was used last time.
Does the response need runtime schema validation? If this panel calls an internal endpoint your own team owns and versions together with the frontend, the response shape is unlikely to drift without your own PR causing it. If it calls a separate, independently-deployed service (even one on your own backend, if it ships on its own schedule), the response can change shape without your frontend code changing at all — that's exactly the case the earlier lesson on validating API responses at runtime was built for, and it's worth deciding deliberately rather than skipping "because it's probably fine."
Does this data need normalizing? If a piece of activity data — say, the actor who performed the action — is only ever going to render inside this one panel and nowhere else, keeping it as a nested, denormalized blob inside each activity item is simpler and there's no real cost to it. If that same actor's name or avatar is also shown elsewhere on the dashboard (a presence indicator, a filter dropdown) and might change while the page is open, that's the case the earlier lesson on normalizing fetched data addressed — multiple places on screen need to agree on the same underlying record.
What do loading, empty, and error actually look like for this specific panel? Not "does it have a spinner" in the abstract, but the real decision from the very first lesson in this track: what renders while the first fetch is in flight, what renders if the account genuinely has zero recent activity yet (a real, valid state, not an error), and what renders if the request fails — a broken dashboard panel with no fallback UI is a bad look for a feature this small and this visible.
See it in a real thing: the decisions made concrete
// After running the checklist: no push channel needed (a manual refresh
// button is enough for this feature), the endpoint is internal and stable
// (skip runtime validation), the activity actor data isn't reused elsewhere
// on this page (skip normalizing), and all four fetch-lifecycle states
// are modeled explicitly.
type ActivityState =
| { status: "loading" }
| { status: "empty" }
| { status: "error" }
| { status: "success"; items: ActivityItem[] };
function useRecentActivity(accountId: string): ActivityState {
// fetch on mount only — this feature decided it doesn't need polling
// or a push channel, because staleness up to a manual refresh is fine
// ...
return state;
}
The interesting part isn't the code — it's that every line of that comment is a decision this track already gave you the vocabulary and the tradeoffs for. A different feature (say, a live collaboration cursor) would run through the exact same four questions and land on completely different answers: push channel, strict validation of an external service's payload, normalized shared state. The checklist doesn't change; the answers do.
What people usually miss
Watch out
"How time-sensitive is this, really?" is a question about the feature, not a default setting. Reaching for a real-time push channel because it's the most powerful option, without the feature actually needing sub-second freshness, adds real infrastructure cost for no real user-facing benefit.
Schema validation and normalization are both skippable, and skipping them is sometimes the right call. Neither is a rule to apply unconditionally — an internal, tightly-coupled endpoint and data that only ever renders in one place are both real, valid reasons to skip the extra layer, not corners being cut.
The loading/empty/error question is the one most likely to get skipped under deadline pressure, precisely because the happy path is what a feature demo shows off — but it's also the one users hit constantly (an empty state on a brand-new account, a failed request on a bad connection) in ordinary daily use.
These four questions interact with each other. A push-channel decision changes what "loading" even means (an initial snapshot plus a live stream, not a one-time fetch), so the four aren't answered in strict isolation — an earlier answer can change how the later ones apply.
Why this matters in interviews
"Walk me through how you'd build a new feature that needs data from the backend" is a real, open-ended system-design-adjacent question, and running through this exact sequence — freshness, validation, normalization, loading/empty/error — out loud and unprompted is what shows a candidate has internalized data-fetching as a set of decisions, not a single reflexive pattern.