One source of truth
Keep each fact in one record. Anything derived from it is a cache, and the write path refreshes that cache.
Keep each fact in one normalized record. A table, map or index built from that record is a cache. The code that writes the fact also refreshes the cache, before anyone can read the stale copy.
A time-to-live is the wrong refresh when missing the new fact is worse than recomputing it.
Example
A package declares its event subscriptions in its manifest. That manifest is the truth. The subscriptions table is derived from it:
/**
* Package event subscriptions, synced from the runnable version's manifest whenever it
* changes (publish, lock, unlock), like jobs. Handlers run as the member who made that
* version runnable.
*/ Every sync deletes topics the manifest no longer declares and upserts the rest in one transaction. Jobs work the same way. You never edit a subscription or a job schedule directly; you publish a new version and the derived rows follow. See Package subscriptions .
The sandbox bundle cache goes further. It refuses to store anything whose truth could move underneath it:
// Only package-free bundles are cached: package imports resolve to whatever version is
// runnable now, and carry per-bundle access tokens.
if (built.packageIds.length === 0) {
cache.set(cacheKey, built.code) In your packages
Pick one home for each piece of state (see Persist named state ). If a package keeps a summary in packageStorage() that's built from somewhere else, update or delete the summary in the same code that changes the original. Don't keep the same id in two packages; export it from the one that owns it.