Remote / foldkit-remote

If you know TanStack Query, TanStack DB or fate

The same job, done from the other side of the Model:

TanStack Queryfoldkit-remote
useQuery({ queryKey, queryFn }) in a componentData.get(Selection, id) in a Surface; the active Surface fetches
a queryKey you designthe entity, its id and the fields selected; there is no key to design
one cache entry per keyone entity per id, shared by every selection of it
staleTime, refetchOnWindowFocusRemotePolicy, Data.refresh from update
gcTimeretention: what no active Surface reaches is collected
onMutate + setQueryDataoptimistic: [Remote.patch(...)], a layer the settlement removes
invalidateQueriesnot needed for overlap: a result updates the one copy
isPending, isError, dataRemoteData: six states, one exhaustive fold
a QueryClient beside your stateRemote.Model, a field of your Model, changed only by Messages

Two differences change how you build. There are no keys. A TanStack cache is a map from keys you design to results you shape, so two components that want overlapping data either share a key and over-fetch, or hold two copies and invalidate by hand. Remote stores fields by entity and id, and a Surface declares which fields it selects, so overlap is the normal case and a mutation's result is seen everywhere at once. The cache is Model. A QueryClient lives beside your state and is updated by effects; Remote.Model is a field of your Model, changed by the same reducer as everything else, so a screen is a function of the Model, replays from a recording, and is tested without a network.

What Remote does not have: a component hook (it has Surfaces and Foldkit Subscriptions), a devtools panel of its own (Data.inspect and Data.why are the data one would show), and retries on failure (a failed read stays failed until something asks again; see When a read fails).

And TanStack DB, and fate

TanStack DB is a local database: collections populated eagerly (or on demand) from a REST API or a sync engine, live queries that update incrementally, and optimistic transactions rolled back on failure. Its unit is the collection; a screen queries what is already local. Remote's unit is the field: a screen declares which fields of which entities it reads, and only those are fetched, so there is no collection to load first and a page carries what it shows. Remote has no live query engine: Data.filtered and Remote.matching judge the rows a list already holds, and a new list is a server query. Where TanStack DB syncs client-authored writes through a sync engine, that job here belongs to foldkit-sync, and Remote stays the disposable cache of what the server owns.

fate is the nearest cousin: components declare views of exactly the data they need, composed into one request per screen, with a normalized cache that masks what a component did not ask for, and actions with optimistic rollback. Remote's Selections are that strictness, and its store is that cache. The differences are where it lives and what runs it: fate is a React data client, driven by Suspense and Actions; Remote is a Submodel of a Foldkit Model, driven by which Surfaces are active, with no view framework in it.