Implementing Caching
1. Setting Cache-Control Headers
| Directive | Meaning |
|---|---|
| public | Any cache may store |
| private | Browser only — not shared caches |
| no-store | Never cache |
| no-cache | Cache, but revalidate first |
| max-age=N | Fresh for N seconds |
| s-maxage=N | Same, for shared caches |
| stale-while-revalidate=N | Serve stale while refreshing |
| immutable | Will never change (long-lived assets) |
Example: Public CDN cache
res.set("Cache-Control", "public, max-age=300, s-maxage=3600, stale-while-revalidate=86400");
2. Using ETag Headers
Example: ETag enabled by default
app.set("etag", "strong"); // or "weak" or false
// Express auto-generates ETag for res.send()/res.json() responses
3. Implementing Browser Caching
Example: Static assets
app.use("/assets", express.static("public/assets", {
maxAge: "1y",
immutable: true,
etag: false
}));
4. Using apicache Package
Example: Install + use
import apicache from "apicache";
const cache = apicache.middleware;
app.get("/popular", cache("5 minutes"), getPopular);
5. Caching Specific Routes
Example: Per-route TTL
app.get("/news", cache("1 minute"), listNews);
app.get("/products", cache("10 minutes"), listProducts);
6. Setting Cache Duration
| Resource | Suggested TTL |
|---|---|
| Hashed JS/CSS bundles | 1 year + immutable |
| Images | 30 days |
| HTML | 0–60 s |
| API list endpoints | 30–300 s |
| Per-user data | private, no-store |
7. Invalidating Cache
Example: apicache clear
app.post("/products", async (req, res) => {
await db.products.create(req.body);
apicache.clear("/products"); // invalidate the list cache
res.sendStatus(201);
});
8. Using Redis for Caching
Example: Cache-aside helper
import Redis from "ioredis";
const redis = new Redis(process.env.REDIS_URL);
export async function cached(key, ttlSec, fn) {
const hit = await redis.get(key);
if (hit) return JSON.parse(hit);
const value = await fn();
await redis.set(key, JSON.stringify(value), "EX", ttlSec);
return value;
}
app.get("/products/:id", async (req, res) => {
const data = await cached(`product:${req.params.id}`, 300, () => db.products.findById(req.params.id));
res.json(data);
});
9. Implementing Cache-Aside Pattern
Read : App ─▶ Cache (hit) ─▶ return
App ─▶ Cache (miss) ─▶ DB ─▶ store in cache ─▶ return
Write : App ─▶ DB ─▶ delete cache key