I’m trying to deploy Discourse on Shelly Cloud (shellycloud.com). Shelly by default provides Varnish as caching reverse proxy. Other projects that I host there use the same setup and work flawlessly.
Discourse is problematic. Most notably categories and list controllers send cache control headers when accessed anonymously. What happens is that this ‘poisons’ cache:
- Anonymous user accesses Discourse front page
- List controller sees that no user is logged in and sends response with
Cache-control: max-age=60, public
- Varnish helpfully keeps this response in cache. Cache is ‘poisoned’.
- User logs in and is redirected to front page
- Varnish sees that page was cached serves it from memory. It never goes to Discourse as it was instructed not to.
- User sees front page designated for anonymous user.
In my opinion Discourse (nor any other app for that matter) should not have two different caching policies for a single URL. URL should be either cacheable or not. Proxies have no way of knowing that upstream may have this kind of policy.
Vary: Cookie header is not a solution either. Although it will instruct proxy to send cached version for users without cookie (i.e. anonymous) it will also tell to cache each version of page based on cookies. Since each logged in user has different cookies this will quickly fill the cache. Proxy will have to then evict other responses to keep hundreds of copies of home page.
Maybe Discourse could use two namespaces: one for anonymous users that can send caching headers and another one for logged in users. Responses that don’t depend on user being logged in can be made cacheable while responses specific for user should be not.