Skip to main content
Caching makes repeat presents instant and is the foundation of FlowPilot’s offline resilience. A resolved flow is kept in memory and on disk, and the SDK resolves a placement by walking a fail-safe chain that prefers a warm cache and degrades gracefully when the network is slow or gone.

The fail-safe resolution chain

Every present and prefetch resolves a placement through the same ordered chain. Each tier is tried until one yields a presentable flow:
TierSourceNetworkWhen it wins
0Fresh cache hitnoneA cached flow is still within its freshness TTL. Presented instantly.
1Live resolveyesNo fresh cache. Bounded by resolveTimeout (default 4s). On success, validated and cached.
2Stale cache (last-known-good)noneThe live resolve failed or timed out, but an older cached flow exists (TTL ignored).
3Bundled default flownoneEverything above missed. Renders a flow you shipped in the app. See Offline and bundled flows.
If no tier yields a presentable flow, the resolve fails, and you handle it with the host fallback (resolveSession returns null, or the presenter fallback renders). Every analytics event carries the tier it was served from as delivery_source (network, cache, stale_cache, bundled_default), so offline and fallback renders are distinguishable in the dashboard. See Analytics.

The resolve deadline does not strand the cache

A live resolve that hits resolveTimeout degrades the current caller to a fallback tier, but it does not cancel the in-flight request. The resolve keeps running to populate the cache, so the next caller hits a warm Tier 0. A slow network therefore never hangs onboarding, and the cost of a slow first present is not wasted. Concurrent resolves for the same key are also coalesced into one round-trip, so a prefetch and a present that race share a single request.

Cache freshness (TTL)

A cached flow is “fresh” for a number of seconds, after which Tier 0 misses and the SDK re-resolves (falling back to the same entry as stale cache if the network fails). The TTL comes from the resolve response’s cacheTtlSeconds; when the backend omits it, the SDK uses the environment default:
EnvironmentDefault TTL
development0 (a fresh entry expires immediately, so effectively no caching)
staging60 seconds
production300 seconds
Because development defaults to a 0 TTL, prefetching and “fast repeat present” have no visible effect there. Test caching behavior against staging or production. See Configuration.

Identity-scoped cache keys

Cached flows are keyed by an identity fingerprint, a hash of the per-install user ID and any targeting attributes the resolve was personalized by. This guarantees a flow cached for one user (or one A/B variant) is never served to another after an identity change. The stale-cache tier keeps a fingerprint-agnostic last-known-good alias, so a previously-seen flow can still render offline even right after the identity changes.

Enabling and disabling caching

Caching is on by default. Turn it off with cachingEnabled: false:
FlowPilot.configure({
  apiKey: 'fp_live_...',
  appId: 'your-app-id',
  cachingEnabled: false, // every present does a live resolve; no offline cache
});
Disabling caching also disables prefetching (there is nothing to retain), so leave it on unless you have a specific reason not to.

Clearing the cache

// Clear cached flows (memory + disk). Forces the next present to re-resolve.
FlowPilot.clearCache();

// Clear image, icon, font, and bundled-image tracking.
FlowPilot.clearImageCache();
clearCache() is the lever to pull during testing when you have published a new flow version and want to bypass the TTL. In production, prefer attaching the new version in the dashboard and letting the TTL expire.

Common mistakes

  • Testing caching against development. The 0 default TTL means nothing stays fresh. Use staging/production.
  • Disabling caching and expecting prefetch to work. Prefetch is a no-op with caching off.
  • Expecting a republished flow to appear instantly. A fresh cached copy is served until its TTL expires, and the placement must point at the new version. Clear the cache or attach the new version. See Troubleshooting.
  • Assuming offline always works. Offline rendering needs either a prior cache entry or a bundled default. Ship a bundled default for guaranteed offline onboarding.

Troubleshooting

  • Old flow still showing after republish. The cache is fresh, or the placement still points at the old version. Attach the new version, then clearCache() or wait out the TTL.
  • First present is slow on a poor network. Expected on a cold cache. Ship a bundled default and prefetch at launch so Tier 0/Tier 3 cover the first present. See Prefetching.
  • A flow renders offline that you did not expect. It came from stale cache or a bundled default. Check the delivery_source in debug logs.