Good questions! It isn't quite as straightforward as you might expect - the interconnected nature of graph-like data means that strategies that work for HTTP don't necessarily apply.
For example, storing per-field expiration times could incur additional memory overhead (you might end up with an object per field instead of per record). Storing per-record expiration times is tricky since the same record can have different fields fetched at different times. And a simple max cache size + LIFO/LRU/etc evication strategy means that the cache might evict a record that is still referenced by a view.
This type of TTL/expiration is something that we're continuing to explore.
But, wouldn't "garbage collection" solve the problem of many React web apps of consuming too much RAM (e.g. when using Redux, you never expire some keys and throughout the application lifecycle, you never cease of accumulating data inside your stores which makes RAM consumption goes up) ?
Could we go ahead and implement proper caching as HTTP would do: expiration date per field/models, then eviction based on expiration dates? With an optional max cache size using LIFO, last used or the current model.
That way we don't need to refetch data if the API is set up to cache. It's sort of frustrating that staleness is just defacto ignored by UI right now.