Caching, CDN, and Data Freshness for Frontend Leads
How to make an app feel instant without showing stale data: a practical guide to browser cache, edge cache, and revalidation policy.
Learn how cache layers work together, what should be cached, and how to balance speed with freshness so users get a fast experience without trust-breaking stale data.
Core concepts
The first job of caching is perception. If the page appears instantly, the user feels progress even before the freshest data arrives.
The second job is correctness. Some screens can tolerate a little staleness, but user-specific or sensitive data usually cannot.
- Public content can usually tolerate more caching than private content.
- The more important the freshness, the tighter the cache policy should be.
- A lead should treat freshness as a product rule, not a guess.
Browser cache helps one user reuse assets and responses locally. CDN cache helps many users in nearby regions get the same public content quickly. Origin cache reduces pressure on the application server, while app cache often manages data inside the client runtime.
When you understand which layer answered the request, it becomes much easier to explain why the page was fast, why the data was stale, or why a refresh still had to hit the backend.
- Browser cache is best for static assets and repeatable responses.
- CDN cache is best for shared public content and traffic spikes.
- Private or session-bound data should usually avoid edge caching.
`Cache-Control` is the main policy switch. `max-age`, `s-maxage`, `no-cache`, `no-store`, and `stale-while-revalidate` each describe a different balance between speed and correctness.
`ETag` and `Last-Modified` help the client ask, 'Has anything changed?' For static assets, versioned filenames are often the cleanest way to avoid accidental stale content after deploys.
- Use `no-store` when the response should never be persisted.
- Use revalidation when the user can tolerate a short period of staleness.
- Versioned file names are safer than manual cache clearing for static assets.
A product list can often be cached for minutes, while a cart, notification badge, or payment status needs much tighter control. The key idea is to match the policy to the risk.
For many product screens, the best pattern is fast initial render plus background refresh. That gives users speed first and freshness shortly after, which is often better than blocking the screen until the backend returns perfect data.
- Stable shared data can be cached aggressively.
- User-specific state should be protected more carefully.
- The freshness policy should be decided before the screen ships.
Visual model
Practical examples
GET /_next/static/chunks/app-shell.4f92a.js200 OK
Cache-Control: public, max-age=31536000, immutable
{ ...built asset bytes... }GET /api/products?category=chairs200 OK
Cache-Control: public, s-maxage=300, stale-while-revalidate=60
{
"items": [
{ "id": "p_1", "name": "Oak chair" }
]
}GET /api/cart200 OK
Cache-Control: no-store
{
"items": [
{ "id": "sku_1", "qty": 2 }
]
}GET /api/profile
If-None-Match: "profile_123_v8"304 Not Modified