Build a reactive data-fetching utility with Svelte stores

Tests store composition for async data fetching with caching and auto re-fetch. Strong answer: readable for lifecycle, derived's set callback for race-safe fetches, writable for private inputs. Red flag: exposed internals or missing cleanup.
What's really being asked
Your ability to treat Svelte stores as composable reactive primitives rather than simple global variables. The interviewer wants to see that you understand the store contract, can encapsulate complex async logic, and know how to manage lifecycles and race conditions in a reactive system.
The full answer
First, create writable stores inside a factory closure for mutable inputs and internal state such as a cache map or current request parameters. Keep these private so consumers cannot mutate loading or cached data directly. Second, return a readable store with a StartStopNotifier that sets up side effects when the first subscriber arrives and tears them down when the last leaves. This gives the utility a clean public boundary. Third, use derived with the async overload that receives a set callback to watch the private writable dependency stores. When dependencies change, the derived callback should start the fetch, call set to emit loading state, then emit data or error state when the promise resolves. It must also return a cleanup function or use an abort controller to cancel in-flight requests when dependencies change again. Fourth, expose methods like setParams or refresh that write to the internal writable stores, triggering the derived chain automatically while keeping the API ergonomic.
The mistakes people make
Using the synchronous form of derived for async work, which fails because derived must return a value immediately. Exposing writable stores directly so callers can corrupt loading or cache state. Putting fetch logic inside a readable start function without wiring it to dependency changes, which breaks automatic re-fetching. Forgetting to handle race conditions, leading to stale requests overwriting fresher data. Ignoring the cleanup contract in derived or readable, which causes memory leaks when components unmount or dependencies churn.
What usually comes next
How do you prevent memory leaks if dependencies change faster than the network? How would you add a manual refresh without breaking encapsulation? How would this pattern translate to Svelte 5 runes like effect and derived? What happens to in-flight requests when the last subscriber unsubscribes from the readable store?
A concrete example
A createQuery factory accepts a writable pageSize store. Inside, writable cache and params stores are declared. A derived store watches params; when pageSize changes, the derived callback checks the cache, emits a loading state via set, initiates a fetch with an AbortController, and ignores the response if a newer request starts before it resolves. The readable store wraps this derived stream and exposes it publicly, while a setPageSize method writes to the internal writable params store. Components subscribe to the readable store and receive an object shaped like data, loading, and error without ever touching the internals.
Interview question
When the derived store's dependencies change while a fetch is still in-flight, what must the callback do to keep the utility race-safe?
- a.Queue the new fetch until the original one resolves to guarantee order and avoid duplicate requests
- b.Return a cleanup function or use an AbortController to cancel the stale request and ignore its resultCorrect
- c.Let the original promise resolve and overwrite the store so no network response is discarded
- d.Invoke the readable store's StartStopNotifier to teardown and recreate the subscription before starting the new fetch
Why? this is the answer
The derived callback must cancel or ignore stale requests—typically by returning a cleanup or using an AbortController—so that slower, older responses cannot overwrite fresher data. Simply letting the original promise resolve causes the exact stale-overwrite race bug the pattern is meant to prevent.
Just read this? Test yourself on what you have been reading.
Read the original → svelte.dev
- #svelte
- #stores
- #reactivity
- #data-fetching
- #advanced
You just looked this up. Could you explain it out loud?
That is the part interviews actually test. Tezvyn takes questions like this one and gives you what the interviewer is really checking, the answer that lands, and the mistake that ends the conversation, in the four minutes before your next meeting.
The iPhone app is on the way
We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.
Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.
We are hiring for this. Open roles that interview on svelte — each one lists the topics its interview covers.
See open roles