Fetch cache (next.revalidate)
Server-side fetch(url, { next: { revalidate: 10, tags: ["echo-demo"] } }) caches the upstream response for 10 seconds. The outer timestamp ticks on every refresh; the inner receivedAt from the cached fetch stays frozen for the freshness window.
Output
Outer (live): 2026-09-06T04:03:32.759Z
Cached receivedAt: 2026-09-06T04:03:32.775Z
Full response JSON
{"method":"GET","path":"/api/echo","query":{"key":"fetch-cache-demo"},"headers":{"user-agent":"ureq/2.12.1","content-type":null},"body":null,"receivedAt":"2026-09-06T04:03:32.775Z"}How it works
The fetch polyfill in the V8 host forwards options.next through to __httpFetch, which consults bext_core::cache::fetch_cache::FetchCache before touching the network. On a hit, the cached JSON envelope is returned directly. On a miss, the upstream call runs and the response is stored under hash(url, method, body), indexed by every tag in next.tags.
revalidateTag(tag) from @bext-stack/framework/cache calls __bextRevalidateTag on the host, which walks the tag index and drops every entry tagged with that string. Cross-worker fan-out via the existing PURGE wire frame is a follow-up; today the invalidation is process-local.
import { revalidateTag } from "@bext-stack/framework/cache";
// Fetch with cache config — response is stored for 10 s,
// indexed under the tag "echo-demo" for targeted invalidation.
const r = await fetch("/api/echo?key=demo", {
next: { revalidate: 10, tags: ["echo-demo"] },
});
const data = await r.json();
// Elsewhere — drop every cached entry tagged "echo-demo".
revalidateTag("echo-demo");