Documentation
Docs
Introduction
Getting Started
Tutorial: build an app
Core Concepts
Routing
Server-Side Rendering
Mimir, state management
Pages & Layouts
API Routes
Styling & Theming
Building & Deploying
API Reference
Guides
Recipes
FAQ (use cases)
Caching and invalidation
rune keeps an in-memory cache of the HTML it renders for static SSR routes. A cache hit serves stored HTML
directly, no React render. You control how long entries live (ttl), label them (tags), and bust them
(app.invalidate).
What gets cached
A static route with an ssr(). The cache key is the path. Each entry stores the assembled HTML, the
atoms used, a timestamp, the ttl, and the tags.
Dynamic routes and shell routes are not cached (they render per request / on the client).
TTL , time-based expiry
Set ttl (in seconds) in the route meta. A cached entry is served while it is fresh; once Date.now() -
timestamp >= ttl, the next request re-renders and re-caches.
ttl: 0 (the default) means no time-based expiry, the entry lives until you invalidate it explicitly.
For content that only changes on deploy, ttl: 0 + explicit invalidation is ideal; for content that drifts
on a schedule, a ttl keeps it fresh automatically.
Tags , group related pages
Attach tags to routes so you can invalidate a whole group at once:
Now publishing a post can clear every blog page in one call.
app.invalidate(pathOrTag)
Three forms:
| Call | Effect |
|---|---|
app.invalidate("*") | Clear the entire cache and re-render every static SSR (non-dynamic) route. |
app.invalidate("/blog") | Clear the entry for /blog and re-render that route. |
app.invalidate("blog") | Treat the string as a tag: clear (and re-render) every cached page carrying that tag. |
A path argument starts with /; anything else is a tag. After invalidation, the affected static routes are
re-rendered immediately so the next request is a warm hit again.
The returned handle from app.start() also exposes invalidate, so background jobs can bust the cache:
A content-update flow
The client never sees stale HTML for those pages after the call, and you did not restart the server.
Cache and __user
A cached entry's HTML is shared, but rune patches the current request's __user into it on the way out
(replacing the "__user":null placeholder). So per-request identity is preserved even on a cached page,
while the rendered markup stays shared. Do not, however, bake per-user markup into a cached static route,
see SSR and hydration → Rule 3.
Choosing a caching policy
| Content | Policy |
|---|---|
| Docs, marketing (changes on deploy) | ttl: 0, eager; invalidate on deploy (restart re-renders anyway) |
| Blog/news (changes during runtime) | tags, invalidate on publish; optional ttl as a safety net |
| Frequently changing widgets | a ttl, or render on the client and fetch fresh data |
| Personalised pages | not cached, render per request / client |
Next: the head tags those renders inject, SEO.