Caching POST Requests | @express-route-cache
How to safely cache POST and non-GET requests using explicit enabling, custom keys, and the type-safe generateCacheKey helper.
Caching POST Requests
By default, @express-route-cache only caches GET requests. Standard mutation HTTP methods (POST, PUT, PATCH, DELETE) bypass the caching layer entirely and trigger auto-invalidation instead. This prevents accidental caching of destructive actions (e.g. creating a user or making a purchase).
However, some endpoints use POST for read-only or idempotent operations, such as:
- Search APIs where the query parameters/filter payloads are too large to fit in a standard
GETURL limit. - GraphQL APIs which route all queries and mutations via
POSTrequests.
This guide explains how to safely enable and configure caching for these routes.
1. Enabling Caching for non-GET Requests
To cache a POST request, you must explicitly enable it at the route level. The global configuration default enabled: true only applies to GET requests.
You can set enabled: true or pass a dynamic function (req, res) => boolean:
// 1. Enable caching unconditionally for this POST route
app.post("/api/search", cache.route({ enabled: true }), handler);
// 2. Enable caching dynamically based on headers or query parameters
app.post(
"/api/query",
cache.route({
enabled: (req) => req.headers["x-skip-cache"] !== "true",
}),
handler,
);2. Setting a Custom Cache Key
[!WARNING] CRITICAL: The default key generator in
@express-route-cachedoes not parse or incorporate the request body (req.body). If you enablePOSTcaching without specifying a customkey, allPOSTrequests to that URL will share the same cache entry, regardless of what query or body is sent.
To differentiate between different POST bodies, you must provide a custom key generator that incorporates the body payload.
The generateCacheKey Helper
We expose a type-safe generic utility function called generateCacheKey to make hashing custom bodies and tags easy:
import { generateCacheKey } from "@express-route-cache/core";
// Signature:
// generateCacheKey<T>(tag: string, data: T, prefix?: string): string;Inside your route options, pass a key resolver using generateCacheKey:
import { generateCacheKey } from "@express-route-cache/core";
app.post(
"/api/search",
cache.route({
enabled: true,
// data is req.body (generic T). We pass "" as the prefix
// so that cache.route can prepend the global prefix (e.g., "erc:")
key: (req) => generateCacheKey("search", req.body, ""),
}),
async (req, res) => {
const results = await performSearch(req.body);
res.json(results);
},
);Hashing URL + Body
If you want the key to be unique to both the specific URL path and the body contents:
app.post(
"/api/graphql",
cache.route({
enabled: true,
key: (req) => {
const uniquenessPayload = {
path: req.originalUrl || req.url,
body: req.body,
};
return generateCacheKey("graphql", uniquenessPayload, "");
},
}),
graphqlHandler,
);3. Dynamic Cache Control (Function Callbacks)
You can specify a function callback for the enabled parameter. This allows you to skip or allow caching based on the request state (e.g. bypass caching for logged-in users, or only cache requests containing specific parameters).
app.post(
"/api/reports",
cache.route({
enabled: (req) => {
// Only cache search requests that look for public data
return req.body.visibility === "public";
},
key: (req) => generateCacheKey("reports", req.body, ""),
staleTime: 300,
}),
reportsHandler,
);Summary Checklist for POST Caching
- Set
enabled: true(or a callback function) on the route middleware. - Specify the
keyoption usinggenerateCacheKeyto hash the request body. - Pass
""(empty string) as the third parameter togenerateCacheKeyto let the cache middleware handle global prefixing cleanly.
Memcached Cache Adapter (memjs) | @express-route-cache
Set up Express.js route caching with Memcached using memjs. Fast, simple key-value caching for production environments that already use Memcached.
Recipes | @express-route-cache
Real-world caching patterns: per-user caching, cache warming, webhook invalidation, conditional caching, multi-tenant setups, and more.