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 THIS TESTS: 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.
A GOOD ANSWER COVERS: 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.
COMMON WRONG ANSWERS: 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.
LIKELY FOLLOW-UPS: 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?
ONE 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.
Source: svelte.dev
Read the original → svelte.dev
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.