no-cache for Personalized Content
Learn how to use no-cache and private directives to handle personalized content that must be fresh but can still benefit from conditional request optimization.
Detailed Explanation
Caching Personalized Content
Personalized pages — dashboards, profiles, recommendation feeds — cannot be cached in shared caches because they differ per user. But they CAN benefit from browser caching with revalidation.
The Recommended Header
Cache-Control: private, no-cache
This combination means:
- private: Only the user's browser may cache (CDN must not)
- no-cache: Browser must revalidate before serving
Why Not just no-store?
no-store forces a full download on every request. For a dashboard page that weighs 50KB but changes only occasionally, this wastes bandwidth. With no-cache:
- Browser sends
If-None-Match: "etag-123" - Server checks if content changed
- If unchanged →
304 Not Modified(0 bytes body) - If changed →
200 OKwith full response
On a typical dashboard, 80–90% of requests result in 304 responses, saving significant bandwidth.
Server-Side Requirements
For no-cache to work efficiently, your server must support:
- ETag generation: A hash of the response content
- If-None-Match handling: Compare the client's ETag with the current version
// Express.js example
app.get('/api/dashboard', (req, res) => {
const data = getDashboardData(req.user);
const etag = generateETag(data);
if (req.headers['if-none-match'] === etag) {
return res.status(304).end();
}
res.set('Cache-Control', 'private, no-cache');
res.set('ETag', etag);
res.json(data);
});
Avoid These Mistakes
- Never use
publicwith personalized content — CDN could serve User A's data to User B - Don't skip
private— corporate proxies might cache authenticated responses - Always set
Vary: Cookieif personalization depends on session cookies
Use Case
A SaaS dashboard shows user-specific metrics, notifications, and recent activity. Using 'private, no-cache' with ETag support, the dashboard page loads instantly from browser cache 85% of the time (304 response in 50ms). The remaining 15% of requests fetch updated content when metrics change. This approach gives users the perception of instant load times while guaranteeing they always see their latest data.