Methods and caching
A quick guide to decide “Will this be cached?” for each method. Based on RFC 9110 cache rules.
Cache basics
Method + headers decide cacheability. GET/HEAD responses are cacheable by default unless told otherwise.
By method
| Method | Cacheability | Notes |
|---|---|---|
| GET | Cacheable | Shared caches may store unless Cache-Control forbids. |
| HEAD | Cacheable | Same as GET, without a body. |
| POST | Normally not cached | Can be cached only with explicit directives and cacheable status (rare in practice). |
| PUT/PATCH/DELETE | Not cached | State-changing by design; caches must not store responses. |
Cache control headers
Response headers define lifetime and scope.
Key headers
- Cache-Control: max-age, s-maxage, no-cache, no-store, private, must-revalidate to set lifetime and revalidation rules.
- ETag/Last-Modified: tags or timestamps for revalidation. Use with conditional requests.
- Vary: list request headers that affect the response (Accept-Language, Authorization, etc.). Required for CDNs.
- Expires: legacy expiry; Cache-Control overrides but often coexists.
Caching POST responses
Allowed by spec, but only when conditions are explicit. Otherwise, assume no caching.
When it can happen
- Status is cacheable (e.g., 200, 203, 204, 206, 300, 301, 404, 410).
- Cache-Control explicitly allows storage (public, max-age, etc.).
- Vary is set correctly; otherwise responses may leak across users.
- Use private when bodies contain user-specific data to keep them out of shared caches.
If you want to forbid it
- Set Cache-Control: no-store for sensitive responses like token issuance.
- Requests with Authorization are not stored by shared caches by default (RFC 9110 13.5.2). If you override with public, do so carefully.
Revalidation and invalidation
Lean on conditional requests for GET/HEAD to avoid full downloads.
Practical tips
- Emit ETag and honor If-None-Match to return 304 when unchanged.
- To prevent any caching, use Cache-Control: no-store or Cache-Control: no-cache, max-age=0.
- When invalidating, bump ETag/version or force revalidation with Cache-Control: no-cache.
Takeaway
Treat GET/HEAD as cacheable by default; POST only caches when you say so. Use Cache-Control and ETag deliberately, and fall back to no-store when in doubt.