# @wrnexus/cache Bounded in-memory/tag caching and HTTP response caching for WRNexusJS. Supports request deduplication, tag invalidation, ETags, fresh/stale states, and optional detached stale revalidation. ```ts import { connectCacheInvalidation, TagCache, responseCache } from "@wrnexus/cache"; const cache = new TagCache({ ttlMs: 60_000, staleWhileRevalidateMs: 300_000 }); export default responseCache({ cache, tags: ["products"] }); ``` `TagCache` bounds entries with LRU-style eviction, deduplicates concurrent loaders, and prevents an invalidated in-flight loader from repopulating stale data. Use `lookup()` when fresh/stale state matters, or `getOrLoad()` for stampede-safe loading. For multi-instance applications, connect the cache to any compatible pub/sub bus (including `@wrnexus/pubsub`). Namespaces isolate applications sharing the same broker. Local invalidation happens first and the returned promise confirms cross-instance publication; failures remain visible to the caller. ```ts import { connectCacheInvalidation, TagCache } from "@wrnexus/cache"; import { createPubSub } from "@wrnexus/pubsub"; import { redisDriver } from "@wrnexus/pubsub/redis"; const cache = new TagCache({ maxEntries: 10_000 }); const bus = createPubSub(redisDriver(process.env.REDIS_URL)); const invalidation = connectCacheInvalidation(cache, bus, { namespace: "storefront-production", onError: (error) => logger.error("cache invalidation failed", { error }), }); await invalidation.invalidateTag("products"); await invalidation.delete("product:42"); // Unsubscribes this cache only; the shared bus remains owned by the app. invalidation.close(); await bus.close(); ``` ## Framework cache layers `CacheCoordinator` keeps the four cache lifetimes explicit: - `coordinator.request()` creates request-only deduplication. - `coordinator.data` caches loader/query results. - `coordinator.component` caches reusable rendered fragments. - `coordinator.page` caches complete safe documents. All cross-request layers are bounded, tag-aware, stale-while-revalidate capable, stampede-safe, and expose `withLock()` for exclusive per-key work. `inspect()` returns metadata without cached values. Development applications expose that inspection through the Cache panel and `GET /__wrnexus/cache`. Pages and components can opt in declaratively: ```wrn cache { scope = "page" strategy = "stale-while-revalidate" ttl = "5m" stale = "10m" tags = ["catalog", "marketing"] vary = ["tenant", "language"] } ``` Omit `scope` to cache named loader data. Use `scope = "page"` for full-page caching. Component policies cache their rendered fragment. Authenticated user and tenant identities are always included automatically; page caches also vary by language, theme, and accent. Add header names or `cookie:name` entries for other application-specific variation. Pages containing CSRF forms are never stored in the full-page cache.