PATTERN Cited by 1 source
Stale-while-revalidate from IndexedDB¶
Shape¶
A client-side cache pattern that pairs the stale-while-revalidate semantic with IndexedDB as the persistent storage substrate, optionally fronted by a synchronous in-memory cache tier. On every navigation, the client renders immediately from the local cache if a value exists, then revalidates against the origin in the background and reconciles the in-memory store on diff.
In its full three-tier form (the GitHub issues#show shape):
read path (hottest first):
React in-memory store ← already-rendered payload
↓ on miss
in-memory cache ← synchronous; hot payloads served without async boundary
↓ on miss
IndexedDB persistent cache ← survives tab close + restart; async read
↓ on miss
network ← background revalidation, populates all three tiers
When to use it¶
- The application is a long-running web app where users revisit the same resources repeatedly (issue triage, collaboration loops, browsing across tabs).
- The data is bounded-stale-tolerant — a few seconds of cached-vs-server divergence on read is acceptable product-wise.
- You want to render-from-cache instantly on soft navigation, not pay a network round-trip per click.
- You want the cache to survive browser restart and tab close.
If any of these is false (write-heavy / strict-consistency- required / single-session / disposable), use a simpler tier (plain in-memory only, or origin-only).
Read path (canonical sequence)¶
- User initiates a soft navigation.
- Look up the resource in the active in-memory store.
- If absent, look up in the in-memory cache (synchronous).
- If absent, look up in IndexedDB (async).
- If found at any tier, render immediately from that value.
- In parallel, issue a background fetch to the origin.
- On origin response: if the new value differs from cached, reconcile the in-memory store and re-render; write through to the in-memory cache and IndexedDB.
Write path¶
- Every successful network fetch writes through to all three tiers (in-memory store, in-memory cache, IndexedDB).
- Cache eviction policy in the in-memory tier is bounded by available memory; in IndexedDB it is bounded by quota + application-controlled TTL.
Failure handling¶
The pattern's graceful-degradation property is load- bearing: "when network is degraded, users still get a usable page from cache, with freshness reconciled once connectivity recovers, introducing a new graceful-degradation model." (Source: sources/2026-05-14-github-from-latency-to-instant-modernizing-github-issues-navigation-performance)
If the origin is unreachable, the cached value is served unchanged; revalidation is retried (or queued) until connectivity returns.
The cache-hit-ratio viability threshold¶
Before committing to the architecture, GitHub set an explicit
cache-hit-ratio floor for the design to be worthwhile:
"Our pre-workstream analysis showed a strong repeated-access
pattern: users reopen the same issues frequently during triage
and collaboration loops. Based on that behavior, we estimated a
potential cache-hit ratio of roughly 30 % for issues#show
and used that as the initial viability threshold." The
post-rollout observed ratio of ~33 % cleared the threshold and
validated the architecture.
This is a defensible discipline: a SWR-from-IndexedDB cache is only worth building if the observed cache-hit ratio will exceed a numerical floor that justifies the engineering cost plus the staleness cost. Build it only if your access-pattern data predicts hitting the floor.
Quantified outcomes (canonical instance)¶
GitHub's issues#show rollout, Step 1 (cache layer alone, no
preheating yet):
- Pre-launch React-soft-nav instant share: 4 %
- Post-launch instant share: 22 %
- Total request volume affected: ~15 %
- Cache-hit ratio: ~33 %
- Server/cache divergence rate: 4.7 %
After preheating and the in-memory tier were added on top, instant share went to ~70 % and cache-hit ratio to ~96 %.
Tradeoffs (named)¶
- Controlled staleness vs latency. "This is not 'cache or correctness.' It is latency-first rendering with asynchronous consistency checks on the same navigation." The 4.7 % cache/server divergence at GitHub is treated as an explicit operating envelope.
- IndexedDB asynchronous reads. Even the persistent layer has an async boundary on the critical render path. The in-memory tier in front of IndexedDB is what eliminates this for hot payloads — see patterns/pair-fast-small-cache-with-slow-large-storage.
- Quota and eviction. IndexedDB quota is browser-scoped and not infinite; high-write workloads can hit quota limits.
- Cache-hit-ratio floor must hold in production. If the predicted ~30 % floor doesn't materialise, the engineering cost has been spent for marginal gain.
Relationship to other patterns¶
- patterns/async-refresh-cache-loader — same SWR
semantic at server-application altitude (Caffeine
refreshAfterWrite); this pattern is the browser-altitude realisation. - patterns/service-worker-cache-hint-header — extends this pattern across hard-navigation boundaries via a cooperating service worker.
- patterns/pair-fast-small-cache-with-slow-large-storage — the in-memory + IndexedDB tiering is this generalised pattern at browser altitude.
Seen in¶
- sources/2026-05-14-github-from-latency-to-instant-modernizing-github-issues-navigation-performance — canonical wiki instance. Three-tier cache (in-memory store
- in-memory cache + IndexedDB) on
issues#show; SWR read path with background revalidation; ~33 % observed cache-hit ratio (pre-preheat) clearing the ~30 % viability threshold; 4.7 % server/cache divergence treated as operating envelope; graceful degradation on network failure.
Related¶
- concepts/stale-while-revalidate-cache — the SWR primitive this pattern realises at the browser altitude.
- concepts/cache-hit-rate — the load-bearing metric.
- concepts/preheating — the cache-population discipline paired with this pattern at high-fanout source surfaces.
- systems/indexeddb — the persistent substrate.
- patterns/async-refresh-cache-loader — sibling SWR pattern at server-application altitude.
- patterns/pair-fast-small-cache-with-slow-large-storage — the tiering shape generalised.
- patterns/service-worker-cache-hint-header — extension across hard-navigation boundaries.
- systems/github-issues-show — canonical wiki instance.