Who this is for. Developers building member areas, carts or anything personal on a site that caches. Afterwards you can predict which requests are served from the cache, which render, and why a personal element on a public page needs a fragment.
The rule has two halves. A response rendered for a signed-in visitor is never written to the page cache. But the page cache is read before the platform knows who is asking, so a page that is stored is served to everyone, signed in or not. A third, smaller effect sits beside them: a request that carries a session cookie or an Authorization header does not use the shared Memcached layer while it renders.
The rule
| Signed-out visitor | Signed-in member | |
|---|---|---|
| Served a stored page, if one exists for the URL | Yes | Yes |
| A rendered response written to the page cache | Yes, if cacheable | No |
| Shared Memcached used while rendering | Yes, on production, unless the request carries PHPSESSID | No: a signed-in member always carries PHPSESSID |
The middle row is the half people know. The first row is the one that surprises them: the page cache is answered from a file before the application starts, its key is the hostname, the path and the declared query parameters, and no cookie or header is part of it. Tested on a production Core dna site in October 2026: requests carrying a token cookie, a PHPSESSID cookie or an Authorization: Bearer header all came back X-Cache-Status: hit with X-Authenticated: 0, the copy rendered for an anonymous visitor.
The members guide states the same rule from the member's side, with the fragments that follow from it: A member site and the page cache.
What it means for member areas and carts
A member area and a cart are fast because they are small, not because they are cached: every request for them renders. Pages under /my-account send a signed-out visitor to the sign-in page, so no anonymous 200 is stored for them, and a signed-in render is never stored either. The cart and checkout routes prevent caching themselves. Their cost is the render, so the template habits in Making pages fast (query-per-row, nesting) matter more on those pages than anywhere else.
A public page is the opposite case. The first anonymous visitor's render is stored and every later visitor gets it, members included. Anything personal on it, such as a name, a cart count or a members-only banner, is either missing for members or, worse, shows someone else's. That is why the personal parts of a public page are fragments, fetched by the browser from a URL that renders for each visitor (Hybrid builds, a cached shell with member fragments).
What it protects, and what it does not
- It protects members from each other. Nothing rendered for a member is written to a shared copy, so one member's details cannot be stored and served to another.
- It does not protect a public page from anonymous assumptions. A template that branches on
$_currentUser->isLoggedIn()on a public page is right for the request that rendered it and wrong for everyone after. - It does not decide access. Access to a members-only record is checked when the record is loaded, so a restricted page is never rendered for an anonymous visitor and never stored. It is the public pages that link to it, or list it, that need care.
- It does not cover the browser. A member's browser may keep its own copy of a public page for the rest of the page's lifetime (the CDN and the browser).
The Memcached half
The shared Memcached layer holds framework internals, not your content (shared Memcached). A request with a PHPSESSID cookie or an Authorization header skips it and works from the in-request cache alone, so the framework repeats set-up work, such as reading entity metadata, that an anonymous request finds ready. Two consequences:
- Every render for a signed-in member does a little more work than the same render for a visitor. That is the price of the session, and another reason member pages should be small.
- An integration calling the API renders without Memcached on every call. Fewer, larger requests cost less than many small ones (Shaping the response with properties).
Checking which case you are in
Two response headers answer it. X-Authenticated is 1 when the platform rendered the response for a signed-in user and 0 otherwise, including on every page served from the cache. X-Cache-Status says whether the response came from the page cache (reading the headers). Look at them as a member in the browser's Network panel, then for the same URL signed out: