Caching when cookies are set

Hi,

I know that cookies often make pages uncacheable, but wanted to explore a particular scenario anyway…

Let’s say the server sets “Vary: Cookie”. There is a cookie named “mode”, which could be A or B. So the versions of the page are

  • no cookies
  • cookie “mode”==“A”
  • cookie “mode”==“B”

That’s three versions of the page. It seems plausible that Fastly could cache, and serve, those versions of the page.

Continuing on, add another similar cookie “screentype”, with two choices. Now the list of all variations are:

  1. no cookies
  2. cookie “mode”==“A”
  3. cookie “mode”==“B”
  4. cookie “screentype”==“C”
  5. cookie “screentype”==“D”
  6. cookie “mode”==“A”, cookie screentype"==“C”
  7. cookie “mode”==“A”, cookie screentype"==“D”
  8. cookie “mode”==“B”, cookie screentype"==“C”
  9. cookie “mode”==“B”, cookie screentype"==“D”

That’s nine versions of the page.

  • With low-granularity, low-variability cookies such as these, will Fastly cache the pages or determine they are uncacheable?

  • How much variability is permitted? How many variations of the same page with different cookie values? 100? 50? 3? What is the cutoff? This is probably the main question. What is the limit.

  • When too many variations are observed, and it stops caching, does that include all versions, or are a few cookied versions still retained in cache? At least the no-cookie copy would continue to be cacheable right?

  • Are these specific answers already in the docs? (which url? If so, that might be enough)

Thanks.

Hi @sdarwin,

There are a couple of answers to this. The strictest one is to say it should be fine to do what you are proposing.

The number of allowed variants depends on whether you are using our compute or VCL platforms, and is explained here under “Limitations and constraints”:

Some other useful resources are linked here:

However, in practice, it’s virtually never effective to vary on the Cookie header.

When you refer to “versions of the page”, you’re citing differences based on the response, but actually the way Vary works, the versions are distinguished by aspects of the request. The variants we store are responses, but they are identified by differences in the request.

This is important because even if your server only sets these two low-variability cookies and you think you only have nine permutations, any other script on the page that sets first party cookies (Google Analytics, for example) will add to the value of the cookie header, and often the value added will be a unique ID, making it immediately impractical to vary on cookie. So you end up with requests that look like this:

Cookie: mode=A; screentype=C; _ga=GA1.1.776025404.1601264836; _ga_48KEBTY0QWK=GS1.1.1693218659.4.0.1693218665.0.0.0;

Cookies may also appear in any order in the header, and Cookie: mode=A; screentype=C is considered different to Cookie: screentype=C; mode=A.

Bottom line, unless you’re aware of these effects and understand that your Vary policy will still be effective, don’t vary on Cookie.

Instead, consider varying on a private header. If you’re using VCL, you can extract those two cookies from the cookie header when Fastly starts handling the request, and add them as separate headers:

set req.http.Fastly-Mode = req.http.cookie:mode;
set req.http.Fastly-Screen-Type = req.http.cookie:screentype;

Then you can use these in the response you serve from your origin server:

Vary: Fastly-Screen-Type, Fastly-Mode

This is super efficient, because some requests might not prompt the origin server to consider the ‘mode’, only the screen type. In that case, it doesn’t matter what the user’s mode value is, and you can get away with caching fewer variants.

Hope this helps!

3 Likes

Thanks, that’s a great answer.
It’s causing me to reconsider our current strategy, which is using ‘defaults’, meaning Django sends Vary: Cookie, and also sets cookies for logged-in users. If those factors are combined, it sort of works correctly: Each logged in user will see their own content, their own profile photo, and so on. But what’s happening behind the scenes… the cache will fill up to the maximum of 50 variations, beyond which no caching, and then on top of that if I also try to add Cookie: mode=A; screentype=C it’s not going to fit in the cache. Putting too much weight on the Vary: Cookie idea will eventually collapse.

serve from your origin server:

Vary: Fastly-Screen-Type, Fastly-Mode

Ok. but maybe that will be more self-contained if done from VCL itself, not modifying the server.
And then another task, detect cookies of logged in users, and bypass the cache for those request, which had been more or less functional before, now must be dealt with.