Caching
Rendering a page in a real browser costs hundreds of milliseconds to several seconds. Bots often request the same URLs repeatedly, so caching the rendered HTML has a large effect on load and latency.
Built-in in-memory cache
Enable it with --cache-ttl (server) or cacheTtlMs (library), in milliseconds:
headless-prerender serve --cache-ttl 300000 # cache each URL for 5 minutesnew PrerenderServer({ cacheTtlMs: 300_000 });Behaviour:
- Keyed by the exact
urlquery parameter, including its query string. - A cache hit sets the response header
x-prerender-cache: hit. - Expired entries are dropped on the next request for that URL.
- The cache is per process and cleared on restart.
0(the default) disables caching entirely.
Choosing a TTL
| Content | Suggested TTL |
|---|---|
| Marketing / docs pages | 1-24 hours |
| Product / catalog pages | 5-60 minutes |
| Frequently changing data | 1-5 minutes, or rely on an upstream cache |
Caching at the proxy or CDN
For higher throughput, cache the prerender response in front of the service. The rendered HTML is a normal text/html document, so any HTTP cache works.
Nginx proxy_cache
proxy_cache_path /var/cache/prerender levels=1:2 keys_zone=prerender:10m
max_size=1g inactive=24h;
location /_prerender {
internal;
proxy_cache prerender;
proxy_cache_key "$scheme://$host$request_uri";
proxy_cache_valid 200 10m;
proxy_cache_valid 404 1m;
proxy_pass http://127.0.0.1:3000/render?url=$scheme://$host$request_uri;
}Cloudflare
Cache the Worker's fetch to the prerender origin with the Cache API, or put a page rule / cache rule on prerender.example.com.
Invalidation
The built-in cache has no invalidation API - use a short TTL, or restart the process on deploy. If you need precise invalidation, cache at the proxy layer where you already have purge tooling.