How does stale work?
Suven opened this issue · 7 comments
Hey!
I suspected that stale would ship cached content pass its TTL:
- User requests /foo
- /foo is cached with TTL 60 and the key has an age of 65
- Caddy responds with /foo from cache
- Caddy gets a fresh /foo and stores it in cache instead
But that does not seem to be the case. (btw, this is how varnish behaves when setting a grace). So what does stale do?
Hey @Suven actually, the cache-handler uses a stale response if the context allows it.
You must have to set the stale
directive (by default the stale
is equal to 0, and the ttl
directive is equal to 2 minutes). If you don't set any of ttl
and stale
, the stale
value would be 2 minutes (the default ttl
value) + 0 second and it will expire at the same time as the ttl
expires.
You have to set the max-stale
directive in your request Cache-Control
HTTP header to tell to the server that you (as a client) you allow the stale response.
If your stale response contains a stale-while-revalidate
Cache-Control directive it will serve the stale response to the client and revalidate it with the upstream server in background.
Or if your stale response contains at least one of the must-revalidate
, no-cache
or need-revalidation
Cache-Control directive it will revalidate with the server before sending the response to the client.
It will check that the stale response can be served as stale otherwise.
That's how it works for now, but using the bypass
directive we could hack that behaviour and bypass the checks.
This test check that it should work following the RFC https://github.com/caddyserver/cache-handler/blob/master/httpcache_test.go#L349-L432
You have to set the
max-stale
directive in your requestCache-Control
HTTP header to tell to the server that you (as a client) you allow the stale response.
Could this be the reason why I'm getting Cache-Status: Souin; fwd=uri-miss; key=GET-https-example.com-/; detail=INVALID-RESPONSE-CACHE-CONTROL
?
My frontend is in swr and responds with Cache-Control: s-maxage=120, stale-while-revalidate
My caddyfile looks like:
{
cache
order cache before rewrite
}
example.com {
cache
encode gzip {
match {
header !Content-Encoding
}
}
reverse_proxy {upstream 3000}
}
Or is it something else? I'm ferly new to caddy and caching in the reverse proxies
So, changing the frontend behavior to specify the stale value as Cache-Control: s-maxage=120, stale-while-revalidate=120
fixed the issue, but now I'm curious on why this happens.
I mean, since Souin already defaults the stale timer to ttl value, if not defined, should it do the same while reading stale-while-revalidate
when there is a correct value for s-maxage
, instead of triggering the invalid cache control?
Hello @Sandros94, s-maxage=100
tells the response should be stored for 100 seconds on shared caches (public/shared caches should not store authenticated requests/responses).The directive stale-while-revalidate
should contains must contains a value stale-while-revalidate=999
to allow responses to be served only if they're stale for less than 999 seconds.
The directive
stale-while-revalidate
should contains must contains a valuestale-while-revalidate=999
to allow responses to be served only if they're stale for less than 999 seconds.
But reading the related RFC example the behavior that I understand is:
- If
stale-while-revalidate
has a value, then the total TTL of the cache isswr-value + max-age
(s-maxage
overrides themax-age
iirc). - But if
stale-while-revalidate
has no value, then the TTL of the cache should be considered on thes-maxage
value alone.
Or am I reading the documentation wrongly?
public/shared caches should not store authenticated requests/responses
I'm new to caching in reverse proxies and thankfully this is something I read everywhere. But do you have, by any change, something to read on the topic of authenticated requests/responses? I do plan to experiment with this and I wanted to boost some backends that are generally slow. Or should I completely ditch this approach?
P.S.: to disable caching for a particular route is it enough to add no-store
? What if I wanted to store it privately on the browser but not the reverse proxy/cdn?