gio cache explain
Request a URL from a running GioJS server and explain, in plain words, what its X-Gio-Cache header says the cache did.
npx gio cache explain /posts/1pnpm exec gio cache explain /posts/1yarn gio cache explain /posts/1bunx gio cache explain /posts/1gio cache explain <url-or-path> [--base <url>]Reference
| Parameter | Type | Default | Description |
|---|---|---|---|
<url-or-path> (required) | string | - | An absolute http or https URL (https://example.com/blog) is requested as given. A path (/posts/1) is requested from --base, else from the local server. Anything else (posts/1, localhost:3000/) is a usage error. |
--base <url> | string | local server | The server a path is requested from: an http or https URL such as https://staging.example.com. |
-h, --help | boolean | - | Print the help and exit with 0. |
Behavior
The local server is the address it would listen on, resolved like gio dev resolves it: GIO_PORT / PORT / GIO_HOST, the .env files, then gio.toml, with a wildcard host (0.0.0.0, ::) reached on loopback and https when [server.tls] is enabled.
gio cache explain sends one GET without following redirects, prints the status and the X-Gio-Cache value, and explains it:
X-Gio-Cache | What happened |
|---|---|
hit; ttl=N | Served from the Rust page cache without touching Node. ttl is the seconds until the entry goes stale. |
stale; age=N; revalidating | Served from the cache past its TTL while one background render refreshes it. age is the seconds since it was rendered. |
miss; stored | Rendered by the Node worker and stored; the next request is a hit. |
bypass | Not served from the cache. Either rendered and not stored - the page has no revalidate, the request was not GET / HEAD, the render was personalized (cookies, credentials, client address), it set per-request headers, or [cache] enabled = false - or refused by the server itself before Node (a rate-limit 429, a skew 409, a CSRF 403). |
static | A file from public/, a hashed chunk under /_next/static/ or a self-hosted font under /_gio/fonts/, served by Rust without the cache or Node. |
ppr; ... | Partial prerendering: the shared shell came from (or went into) the cache and the Suspense holes rendered for this request. |
| (absent) | An internal /_gio endpoint, or a server older than X-Gio-Cache. The image optimizer, /_gio/image, answers HIT or MISS for its own cache instead; the command prints that value as it is. |
Examples
Watch a page get cached
$ npx gio cache explain /blog
GET http://127.0.0.1:3000/blog
status 200
x-gio-cache miss; stored
→ Rendered by the Node worker and stored in the cache - the next
request for this key is a hit. Pages opt in via `export const revalidate`.
$ npx gio cache explain /blog
GET http://127.0.0.1:3000/blog
status 200
x-gio-cache hit; ttl=60
→ Served from the Rust page cache without touching Node. "ttl" is the
seconds until this entry goes stale.With app/blog/page.tsx exporting revalidate = 60.
A page that is not cached
$ npx gio cache explain /about
GET http://127.0.0.1:3000/about
status 200
x-gio-cache bypass
→ NOT served from the cache. Either rendered by the Node worker but not
stored - the page cache is off (`[cache] enabled = false`), the page did
not declare `revalidate`, the request was not GET/HEAD, the response
varies per user, or it set per-request headers - or refused by the
server itself before Node (a rate-limit 429, a skew 409, a CSRF 403).When a page declares revalidate but its render is personalized (it read cookies or credentials, or set a cookie), the server logs a warning naming the route.
Ask a deployed server
npx gio cache explain /pricing --base https://staging.example.com
npx gio cache explain https://example.com/pricingA local server on another port
gio dev --port 4000 # one terminal
GIO_PORT=4000 gio cache explain / # another--port applies only to the server it starts; tell gio cache explain the same port through the environment, or use --base.
Good to know
- The request carries no cookies, so it sees what an anonymous visitor (and a CDN) sees.
- Exit codes:
0whenever the server answered, whatever the status;1when it could not be reached (is the server running?);2for a usage error, including a target or--basethat is not a path or an http(s) URL (no request is sent). - Each request counts: running it twice on a
missstores the entry, and a request past the TTL starts the background refresh.
Related
Version history
| Version | Changes |
|---|---|
v0.1.0-beta.8 | Paths go to the address the server listens on (GIO_PORT / PORT, .env files, gio.toml) instead of port 3000; --base <url>; explains ppr responses and names [cache] enabled = false and the server's own refusals as reasons for bypass. Self-hosted fonts answer static. A target or --base that is not a path or an http(s) URL is a usage error (exit 2), not an unreachable server. |
v0.1.0-beta.6 | Introduced. |