Running a site
Caching and performance
The page cache
Public pages change only when something is published, so Gansey keeps each rendered page in memory, by path (and by language prefix, when a module serves the site under prefixes). The first request for a page renders it, passes it through any modules listening on page.html and response.headers, and stores the result; later requests are served from memory until the cache is dropped. Only successful HTML responses are stored. The cache lives in the process, so it starts empty on every restart and is not shared between processes.
The whole cache is dropped when:
- a page, entry, site part or the theme is published, unpublished or deleted, including a scheduled publish;
- a content type, taxonomy or term is created, changed or deleted;
- site settings change in Settings → Site;
- a module is installed, removed, reloaded, switched on or off, or its files change on disk;
- a module writes content, changes the cache policy or language prefixes, or clears the cache itself;
- the optimise queue finishes new image copies.
Search results, previews and module routes are never cached.
ETags and revalidation
Every cached page carries a strong ETag taken from a hash of its HTML. A browser or proxy that sends it back in If-None-Match gets 304 Not Modified with no body, so checking a page that has not changed costs almost nothing. The bundled assets and the admin's files carry ETags too.
Cache headers
| What | Cache-Control |
|---|---|
| cached public pages | public, max-age=0, must-revalidate, or the policy's page lifetime |
| pages the policy leaves out of the cache | private, no-cache |
| search, previews, module pages in the site chrome | private, no-store |
bundled assets under /_gansey/assets/ | no-cache, or the policy's asset lifetime |
media under /media/ | public, max-age=31536000, immutable |
the admin's built files under /admin/assets/ | public, max-age=31536000, immutable |
robots.txt | public, max-age=300 |
Media files can be kept for a year because every address includes the item's id, and next-generation copies are named after their content, so a changed file always gets a new address. Bundled assets keep the same address from one release to the next, so by default browsers revalidate them.
Pages outside production also carry X-Robots-Tag: noindex, nofollow (see Security).
The cache policy
A module with the cache permission can set the site's cache policy with ctx.cache.configure:
ctx.cache.configure({ exclude: ["/account", "/shop/*"], page_max_age: 0, asset_max_age: 86400 })
excludelists paths rendered afresh on every request and never stored./accountmatches that path only;/shop/*matches/shopand everything under it.page_max_ageis how many seconds browsers may reuse a page without asking again.0, the default, means they ask every time, which the ETag keeps cheap.asset_max_agedoes the same for the bundled assets.
Lifetimes are capped at a year. The policy applies only while the module that set it is running: switch that module off and the defaults return. Modules can also add response headers to pages, limited to caching, resource-hint and security-policy headers and anything starting x-. See Modules for the details.
The performance module
The official performance module (gansey-module-performance) is the usual way to tune all this from the admin. It chooses which next-generation image formats the media library makes and optimises new uploads, sets the page cache exclusions and browser cache lifetimes, minifies HTML, gives each page's first image priority, and runs page speed audits on demand or on a schedule, keeping their history. The audits call an external page speed audit service, which the module declares in its manifest. Install it from the registry or from its folder:
gansey mod add performance
gansey mod add ../modules/performance # from a checkout
Its settings apply only while it runs. Without it, core makes WebP copies at quality 80 when asked and uses the default cache headers above.