React Forum
Blog & Guide Responses
Mar 28, 2023 · 04:00 PM

[Deep Dive #51] Data Cache Altars - discussion

Started by Theo Bennett
blogcachingledgersofferingsblessingsfreshness

Deep Dive #51 reframes caching as a surface contract: the route shell configures the cache altar, component tracks bring offerings (what they can tolerate), and the shell writes a ledger before it blesses a source (cache/network/stale/ghost). The vocabulary is doing real work here: it makes it possible to talk about what "won this render" without arguing about hidden implementation details.

Read the post

Do you have a cache ledger today (even a tiny one), or is caching still a hidden optimization layer? How do you define 'fresh enough' for a blessing, and where do you render that decision so screenshots are debuggable? For tracks that disagree (network vs cache), do you let the shell choose, or do you let tracks override with their own offerings?

Comments (10)

Back to latest
Dmitri Kline
Mar 28, 2023 · 04:06 PM

The altar metaphor works because it forces explicitness: the shell decides, records, and renders the record.

Related: Data Fetching and Caching (Best Practices).

Maya Henson
Mar 28, 2023 · 04:16 PM

The blessing types (stale/ghost) are interesting because they normalize partial truth.

If your UI admits 'ghost', users can calibrate expectations instead of assuming it's live.

Salma Qureshi
Mar 28, 2023 · 04:28 PM

We did a tiny cache ledger + render marker and it helped triage 'why did it refetch' instantly:

tsx
const ledger = useLiveState('cache:inbox:ledger', { chosen: 'cache' as 'cache' | 'network' | 'stale' | 'ghost' });
return <div data-cache-blessing={ledger.read('chosen')} />;
Priya Liao
Mar 28, 2023 · 04:43 PM

This connects nicely back to Cache Bust Liturgies: you can choose 'bust-by-default' as the shell's policy and still keep it readable via the altar ledger.

Without the ledger, busting just looks like chaos.

Related: Cache Bust Liturgies (Deep Dive #33).

Keira Santos
Mar 28, 2023 · 04:57 PM

Counterpoint: shells choosing everything can make tracks feel powerless.

I like offerings because tracks can communicate tolerances, but I'd still allow a track to request 'network only' when correctness matters.

Theo Bennett
Mar 28, 2023 · 05:03 PM

Agreed. I read the post as: the shell chooses, but the tracks *shape* the choice via offerings and policy.

If a track can't express "no ghost, no stale", the altar turns into a one-size-fits-none cache layer.

Keira Santos
Mar 28, 2023 · 05:06 PM

Yes, exactly. Offerings are only useful if they can actually constrain the blessing.

Grace McCoy
Mar 28, 2023 · 05:18 PM

The best part for me is the reminder that caching is multiple truths at once (network/cache/UI) and the ledger is what makes it survivable.

Related: Core Concepts (Best Practices).

Inez Park
Mar 28, 2023 · 05:32 PM

Policy-per-track is the practical unlock. It is basically a treaty between surfaces. We ended up modeling it explicitly and rendering it so people couldn't "accidentally" change it in a refactor:

tsx
const policy =
  track === 'list' ? { preferCache: true, allowStale: true, ghostMode: true } :
  track === 'thread' ? { preferCache: true, allowStale: false, ghostMode: false } :
  { preferCache: false, allowStale: false, ghostMode: false };

return <section data-track={track} data-policy={JSON.stringify(policy)} />;
Mina Calder
Mar 28, 2023 · 05:47 PM

A misunderstanding I had when I first skimmed: I assumed "ghost" was just a fancy name for stale.

The difference matters in the UI. Ghost is "we are showing cached value that might be deceptive" and the ledger makes that deception visible.

Harper Iqbal
Mar 28, 2023 · 06:01 PM

If you want the vocabulary to stick, you need it in code review.

We started requiring every caching surface to set a blessing and write one ledger line explaining why. It stopped a lot of "mysterious refetch" tickets.

Benji Rios
Mar 28, 2023 · 06:14 PM

This post pairs nicely with the idea that hooks should reveal behavior.

If your cache helper hides the blessing decision, you will end up arguing about performance with no evidence.

Related: API Reference.