Caching: the KV store, the page cache and the data cache
Everything that keeps state between requests (the page cache, the data cache, sessions and rate limits) is built on one interface, KVStore, with get, set,…
Everything that keeps state between requests (the page cache, the data cache, sessions and rate limits) is built on one
interface, KVStore, with get, set, delete, list and increment. A value is JSON data. A TTL (ttlSeconds)
expires an entry. increment sets its TTL when it creates the key.
| Store | Where | Notes |
|---|---|---|
createMemoryKVStore({ maxEntries, maxValueBytes }) |
@shadow-js/dusk/server |
In-process, least recently used. Default 10 000 entries and 1 MiB per value. |
createFileKVStore({ directory }) |
@shadow-js/dusk/node |
One JSON file per key, written atomically. For development and a single server. |
createKvCacheStore, createKvSessionStore, createKvRateLimitStore |
@shadow-js/dusk/server |
Adapters from a KVStore to the page cache, sessions and rate limits. |
Pass a store to the handler to keep the page cache in it: createHandler({ cache: { kv } }). The data cache uses the same
store when one is given, and a memory store otherwise. Sessions and rate limits take the adapter you pass to them.
cacheData(fn, { key, tags, revalidate | cacheLife }) requires a key and an explicit lifetime. The key is an array of
plain data, stored in the query key format (hashKey from @shadow-js/query), so equal data names the same entry
whatever the order of its object properties. revalidate is in seconds: the value is fresh for that long, and the stale
window is as long again (the expiry is twice revalidate). A cacheLife name is a preset (seconds, minutes,
hours, days, weeks, max) or one of yours from the file. Past the fresh window a stale value is returned at once
while one background run refreshes it. An error is never cached, a value that is not JSON is a TypeError, and during
draft mode the function runs every time.
revalidateTag(tag) removes the page-cache entries and the data-cache entries that carry the tag. cachedFetch(url, init, options) caches a public GET request the same way. It refuses authorization, cookie and
proxy-authorization headers, because a shared cache must never hold one user's answer.
Server functions choose the cache-control of a successful answer: serverFn({ method: "GET", cacheControl: { visibility: "public", maxAge: 60, staleWhileRevalidate: 300 } }, handler). The default is no-store. A public answer is only
allowed for a GET function, and it becomes private for a request that carries cookies or authorization. vary lists
the request headers the answer depends on, and profile takes the stale and revalidate times of a cacheLife
profile. Errors are always no-store.