Skip to content

Freshness Detection

The freshness system ensures edge-cached pages stay current without sacrificing performance. It works by embedding version fingerprints in rendered HTML and using client-side JavaScript to trigger background revalidation when data is stale.

How It Works

Version Fingerprints

When the Worker renders a page, it embeds a version hash in the HTML:

html
<div data-controller="freshness"
     data-freshness-type-value="product"
     data-freshness-id-value="tori-tank"
     data-freshness-version-value="a1b2c3d4">
</div>

The version hash is computed from the entity's data at render time. If the origin data changes (price update, stock change, content edit), the hash will differ.

Throttling

To prevent excessive API calls, the Worker throttles freshness checks:

  • Scope: Per URL, per Cloudflare PoP
  • Window: Maximum 1 revalidation per 60 seconds
  • Mechanism: Cloudflare Cache API stores a "last checked" timestamp
  • Effect: Even with thousands of visitors, each page generates at most ~1 origin call per minute per PoP

User Experience

The freshness check is invisible to users:

  1. User sees the edge-cached page immediately (fast)
  2. Freshness controller runs in the background (non-blocking)
  3. If stale, an API call is made to Maho and the DOM is replaced in-place if the data has changed — the current user sees the update without a reload
  4. Data is updated in KV and edge cache is busted
  5. The next visitor to that URL gets the fresh version server-rendered

Worst case: content is ~60 seconds stale. Best case: content is always fresh (no changes on origin).

Freshness by Entity Type

EntityWhat Triggers StalenessTypical Lag
ProductPrice change, stock update, description edit< 60s
CategoryProduct added/removed, position change< 60s
CMS PageContent update in admin< 60s
Blog PostContent update< 60s

Relationship to Caching

Freshness is a safety net, not the primary update mechanism.

The primary path for keeping data current is the Maho admin module — any product, category, or CMS save in Maho triggers an observer that queues a KV update. A cron job processes the queue every minute, pushing changes directly to Cloudflare KV via the /sync endpoint. This means KV should never be stale under normal operation.

Freshness exists to catch edge cases:

  • Edge cache staleness — HTML is cached per PoP with TTLs of 30 min to 4 hours. Even though KV has the latest data, a PoP may be serving an old HTML render. The freshness controller detects this and triggers a re-render.
  • Missed syncs — If the cron queue fails or a sync is delayed, freshness catches the discrepancy.
  • External data changes — Changes made outside the admin (direct DB edits, API imports) won't trigger observers.

In practice: KV is kept current by observer-driven sync, edge cache is kept current by freshness checks, and both work together for sub-minute propagation.

Source: src/index.tsx, src/js/controllers/freshness-controller.js