Restful Caching
title: "RESTful Caching — Cache-Control, ETag, and Conditional Requests" description: "RESTful caching uses Cache-Control headers, ETags, and conditional requests to reduce server load and improve response times for cacheable GET requests." date: 2026-06-28 lastmod: 2026-06-28 weight: 22 tags: [apis, restful] }
RESTful caching leverages HTTP caching semantics with Cache-Control directives, ETag validation, and conditional requests to serve cached responses efficiently.
What You'll Learn
- HTTP caching for REST APIs
- ETag generation
- Conditional request handling
Why It Matters
Caching reduces API response times from 200ms to under 10ms and cuts server load by 90% for cacheable endpoints.
Code Examples
# Cache-Control headers
@app.route('/users')
def list_users():
users = db.get_users()
response = jsonify([u.to_dict() for u in users])
response.headers['Cache-Control'] = 'public, max-age=60'
response.headers['ETag'] = compute_etag(users)
response.headers['Vary'] = 'Accept-Encoding'
return response
# Conditional request handling
@app.route('/users/<int:id>')
def get_user(id):
user = db.get_user(id)
if not user:
return jsonify({"error": "Not found"}), 404
etag = f'"{user.version}"'
if request.headers.get('If-None-Match') == etag:
return '', 304
response = jsonify(user.to_dict())
response.headers['ETag'] = etag
response.headers['Cache-Control'] = 'private, max-age=60'
response.headers['Last-Modified'] = user.updated_at.strftime(
'%a, %d %b %Y %H:%M:%S GMT'
)
return response
# Cache header helper
def cache_response(response, public=True, max_age=60, etag=None):
cache_type = 'public' if public else 'private'
response.headers['Cache-Control'] = f'{cache_type}, max-age={max_age}'
if etag:
response.headers['ETag'] = etag
return response
// Express ETag middleware
const etag = require('etag');
app.get('/api/users', (req, res) => {
const users = db.getUsers();
const hash = etag(JSON.stringify(users));
if (req.headers['if-none-match'] === hash) {
return res.status(304).end();
}
res.set({
'ETag': hash,
'Cache-Control': 'public, max-age=60'
});
res.json(users);
});
Common Mistakes
1. No Cache Headers on GET
Every GET response should have explicit Cache-Control.
2. Caching User-Specific Data as Public
User profile data should use private cache.
3. No ETag on Cacheable Responses
ETags enable efficient conditional revalidation.
4. No Vary Header
Cached responses may be served to wrong clients.
5. Long TTLs Without Invalidation Strategy
Stale data persists when you forget to invalidate.
Practice Questions
- What header makes a response cacheable?
- How does ETag enable conditional requests?
- What is the difference between public and private cache?
- Why use Vary: Accept-Encoding?
- What HTTP status indicates the cached version is still valid?
Answers:
- Cache-Control header.
- Client sends If-None-Match with the ETag; server returns 304 if unchanged.
- Public allows proxies and CDNs to cache; private restricts to browser.
- So cached gzipped responses aren't served to clients without gzip support.
- 304 Not Modified.
Challenge: Add proper caching headers to all GET endpoints. Implement ETag-based conditional responses and test with curl.
FAQ
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro