GioJSdocs
On this page

[cache]

The page cache: a memory LRU in front of a disk directory for pages that export revalidate, with page ETags and stale-while-revalidate.

gio.toml
[cache]
memory_max_entries = 5000
disk_max_bytes = 1073741824     # 1 GiB

Which pages are cached is decided per page, with the revalidate export; this section sizes the cache and switches its parts. Caching & Revalidating explains the model.

Reference

KeyDefaultDescription
enabledbooleantrueStore and serve pages that export revalidate. With false every response answers X-Gio-Cache: bypass and every request costs a render, but pages still send the Cache-Control their revalidate asks for, so a CDN in front can keep caching them.0 / false / empty: Nothing is stored; every request renders
memory_max_entriesinteger1000Pages kept in the in-memory LRU. Pages pushed out of memory are still served from the disk tier. At least 1; enabled = false is the off switch.0 / false / empty: Not allowed: 0 is a startup error
disk_enabledbooleantrueKeep a disk tier behind the memory LRU. It holds what memory drops and outlives restarts. false writes no files: a page the LRU drops renders again, and the cache starts empty after every restart.0 / false / empty: Memory only
disk_pathstring".gio/cache/pages"The disk tier's directory, relative to the project root and below it (not ., not absolute). It must not be, contain or sit inside app/ or public/. GIO_CACHE_DIR overrides it, may be absolute, and is held to the same placement rule.Env override: GIO_CACHE_DIR
disk_max_bytesinteger536870912Size cap of the disk tier (512 MiB); past it the oldest entries are deleted.0 / false / empty: No size bound
etagbooleantrueSend a weak ETag with pages and answer a matching If-None-Match with 304 Not Modified. Turn it off for a CDN that mishandles weak validators, or when the app sets its own.0 / false / empty: No page ETags, no 304
swr_multiplierinteger10A page stays servable stale (while one background render refreshes it) until it is this many times its revalidate old. The same window sizes the stale-while-revalidate directive CDNs read.0 / false / empty: Never serve stale; no stale-while-revalidate

Behavior

X-Gio-Cache on every page response says what happened: miss; stored, hit; ttl=<seconds>, stale; age=<seconds>; revalidating (served stale while one render refreshes it), or bypass (not cacheable, or the cache is off). A page with a cached PPR shell reports ppr; shell=stored, ppr; shell=hit or ppr; shell=stale; age=<seconds>; revalidating. A cached page carries, with revalidate = 60 and the default multiplier:

text
cache-control: public, max-age=0, s-maxage=60, stale-while-revalidate=540
etag: W/"50b12c1658e2f16a5b78a9b93c564426"
  • s-maxage is what is left of the page's revalidate window; stale-while-revalidate is what is left of revalidate × swr_multiplier after that. Browsers always revalidate (max-age=0).
  • A render that read cookies, the Authorization header, the client address, host or scheme (ctx.ip, ctx.host, ctx.scheme), or that sets a cookie, is personal: it is sent private, no-cache and never stored.
  • A page answered to a request with an Authorization header, through a guard, or in a locale negotiated from request headers goes out private, no-cache without an ETag, even when the page cache served it: one URL serves several audiences there.
  • A Cache-Control the app or a [[headers]] rule sets always wins.
  • Entries are keyed by the deployment id: a new build or a change to the settings pages render with drops what an earlier one stored on disk.

Startup logs page cache disabled ([cache] enabled = false): every request renders or page cache is memory only ([cache] disk_enabled = false) when you turn a part off. None of these keys logs a warning.

Errors

  • invalid `cache.memory_max_entries`: invalid value: integer `0`, expected a nonzero usize
  • invalid `cache.disk_path`: expected a directory inside the project, relative to its root (".gio/cache/pages"); use GIO_CACHE_DIR for a path outside it
  • [cache] disk_path: the page cache directory ./public/cache is inside the public/ directory (...) - give the cache a directory of its own, such as .gio/cache/pages
  • unknown key `cache.memory_mb` - the memory cache is bounded by entry count: use memory_max_entries (default 1000), and [cache.redis], which is refused: there is no Redis backend yet.

Examples

A CDN does the caching

Render every request at the origin and let the CDN keep pages for their revalidate:

gio.toml
[cache]
enabled = false

Read-only filesystem

gio.toml
[cache]
disk_enabled = false        # memory only: nothing is written under .gio/cache/pages
memory_max_entries = 2000

Without the disk tier (or with enabled = false) the page cache directory is not even created. The server still creates .gio/fonts (GIO_FONTS_DIR) and, with the image optimizer on, .gio/cache/images (GIO_IMAGE_CACHE_DIR): create them before deploying or point those variables at a writable path. A directory that cannot be created stops startup with its path and the setting that placed it.

Never serve stale pages

A page past its revalidate window renders before it is served:

gio.toml
[cache]
swr_multiplier = 0

Cache outside the project

bash
GIO_CACHE_DIR=/var/cache/my-app npm start

Good to know

  • Each server instance has its own cache. Instances that share a disk directory serve the pages each other stored, but each keeps its own memory LRU - purge every instance.
  • GioJS only ever deletes its own entry files (<sha256>.json) in the disk directory, but give it a directory of its own.
  • In development the cache is cleared each time a source change restarts the worker, and cached pages get no ETag.
  • export const revalidate = false caches a page for a year (31536000 seconds).

Not configurable

  • Personalized renders bypass the cache. There is no switch to store a page that read cookies or the client address: it would be served to everyone. Cache the shell with shell = 'cache' and personalize inside Suspense holes instead.
  • Set-Cookie and hop-by-hop headers are never stored with a page.

Version history

VersionChanges
v0.1.0-beta.8Introduced as a gio.toml section: memory_max_entries, disk_path and disk_max_bytes are honored, and enabled, disk_enabled, etag and swr_multiplier added. memory_mb and [cache.redis] are rejected with a hint. The disk directory may not overlap app/ or public/.