Implementing Caching Strategies
| Scenario | Header Value |
| Static asset | public, max-age=31536000, immutable |
| API list endpoint | private, max-age=60, must-revalidate |
| User-specific | private, no-cache |
| Sensitive data | no-store |
2. Implementing ETag-Based Caching
ETag Validation Flow
- Server returns response with
ETag: "v1"
- Client caches body + ETag
- Next request:
If-None-Match: "v1"
- If unchanged → 304 Not Modified (empty body)
- If changed → 200 OK + new body + new ETag
| Header | Format |
Last-Modified | HTTP-date: Sat, 15 May 2026 10:30:00 GMT |
If-Modified-Since | Same format, sent by client |
| Granularity | 1 second (use ETag for finer) |
4. Using If-None-Match Conditional Requests
| Header | Server Action |
If-None-Match: "v1" | Same → 304; different → 200 + body |
If-None-Match: * | POST: only if not exists (insert-only) |
5. Using If-Modified-Since Conditional Requests
| Header | Server Action |
If-Modified-Since: <date> | Unchanged → 304; modified → 200 |
| Combined with ETag | ETag takes precedence per RFC 7232 |
6. Returning 304 Not Modified Responses
| Required | Forbidden |
| ETag, Cache-Control, Vary headers | Body (must be empty) |
| Same Content-Location | Content-Length, Content-Type |
7. Implementing Private vs Public Caching
| Directive | Cached By |
public | Browser + shared caches (CDN, proxy) |
private | Browser only |
| Default (none) | Cacheable per heuristics |
Tells caches which request headers to include in cache key.
| Vary Value | Cache Key Considers |
Accept | Format negotiation |
Accept-Encoding | Compression variant |
Accept-Language | Language variant |
Authorization | Per-user response |
Cookie | Per-session response |
9. Implementing Cache Invalidation Strategies
| Strategy | Description |
| TTL-based | Expire after max-age; simple, may serve stale |
| Event-driven | PURGE on write; complex but accurate |
| Versioned URLs | /v2/users; bypass old cache |
| Tagged cache (Varnish) | Invalidate by tag (e.g. user:42) |
| Stale-while-revalidate | Serve stale, refresh in background |
10. Caching at Different Layers
Browser → Service Worker → CDN → API Gateway → App Cache → DB Cache → DB
(1) (2) (3) (4) (5) (6) (7)
| Layer | Technology | TTL Range |
| Browser | HTTP cache | Minutes-hours |
| Service Worker | Cache API | Custom logic |
| CDN | Cloudflare, Fastly, CloudFront | Seconds-days |
| App | Redis, Memcached | Seconds-hours |
| DB | Query cache, materialized views | Variable |
11. Handling No-Store Directive
| Use Case | Why no-store |
| Auth endpoints | Tokens never cached |
| Banking transactions | Compliance / privacy |
| PII responses | Avoid intermediary leakage |
12. Understanding Cache-Control Directives
| Directive | Meaning |
max-age=N | Fresh for N seconds |
s-maxage=N | Shared cache override |
no-cache | Must revalidate before serving |
no-store | Don't cache anywhere |
must-revalidate | Stale must revalidate |
proxy-revalidate | Same, for shared caches |
immutable | Won't change for max-age duration |
stale-while-revalidate=N | Serve stale up to N sec while refreshing |
stale-if-error=N | Serve stale on origin error |