Late async results must not overwrite newer ones
An async result must prove it is still wanted before it writes: every path that changes the same field has to invalidate in-flight work, not just the next upload.
Read the lesson →Refresh every store a server change touches
When a server-side change filters several resources, re-fetch every client store that caches one of them, not just the store for the thing you changed.
Read the lesson →Act on live state, not a debounced copy
A store field that mirrors an editor through a debounce is fine for display but wrong for actions; read the source of truth at the moment of the action, and re-check “where am I?” after every await.
Read the lesson →Guard cache writes with scope and a version
In a persisted client cache, every async write needs two guards captured before the await: whose data it is (identity scope) and whether something newer was written meanwhile (a version or mutation counter), because timestamps alone can tie.
Read the lesson →Never roll back a change the server accepted
Put only the server call inside the rollback block; once the server has accepted a mutation, a failed refresh is a logging problem, not a reason to undo the user's change.
Read the lesson →No global store writes during a server render
A client store that is a module singleton becomes shared state across users the moment it runs on a server; pass server-loaded data down per request (context or props), never by writing it into the global store during render.
Read the lesson →Clearing a cache does not stop in-flight loads
When a push event invalidates a cache, every request already in flight must be able to tell it is now stale, and something must start the replacement request; deleting the cache entry alone does neither.
Read the lesson →A paywall bypass also skips the downgrade
A platform flag that skips an entitlement check usually also skips the code that revokes the entitlement: a bypass added to “select” silently disabled “reset on downgrade”, so stale paid state outlived the subscription.
Read the lesson →A full resync is not a cheap retry
A “reset sync” that clears clocks is a full re-download, not a cheap retry: trigger it only from a state that proves sync is stuck, never from mount effects, timers or diagnostics, and never twice at once.
Read the lesson →Clear scoped state before the reload starts
When the scope of a piece of client state changes, clear it before the async reload, not after: otherwise the UI spends the loading window showing, and submitting, values that belong to the previous scope.
Read the lesson →