API Response Caching Middleware for Express/Node
raw JSON → 1.6.3 verified Thu Apr 23 auth: no javascript
apicache is an ultra-simplified middleware for Express.js and Node.js designed to cache API responses. It supports both an in-memory store and Redis as a backend, allowing developers to define cache durations using plain-english strings (e.g., '5 minutes'). The current stable version is 1.6.3, with version 1.0.0 marking a production-ready release after extensive use. The project appears to have a moderate release cadence, focusing on stability and adding features incrementally, such as `res.write` support and official `compression` integration. Its key differentiator is its ease of use and 'automagic' caching injection into routes, making it a straightforward choice for basic API caching needs compared to more complex caching solutions.
Common errors
error TypeError: apicache.middleware is not a function ↓
cause Incorrect import pattern, attempting to destructure `middleware` from `apicache` directly, or not importing `apicache` at all.
fix
Ensure you are importing the default
apicache object: import apicache from 'apicache'; and then accessing middleware as a property: let cache = apicache.middleware; error Error: Redis connection to localhost:6379 failed - connect ECONNREFUSED ↓
cause The Redis server is not running or is not accessible at the specified host and port.
fix
Start your Redis server, verify its configuration (host/port), and ensure your application has network access to it. If using a custom URL, ensure
redis.createClient({ url: '...' }) is correct. error ReferenceError: require is not defined in ES module scope ↓
cause Attempting to use CommonJS `require()` syntax in an ES Module (`.mjs` file or `type: "module"` in `package.json`) environment.
fix
Replace
const apicache = require('apicache'); with import apicache from 'apicache'; error Cache is not clearing/invalidating as expected. ↓
cause Incorrect `apicache.clear()` target, or misunderstanding of cache grouping.
fix
Verify the target string passed to
apicache.clear(target) matches an exact URL path or a req.apicacheGroup name. Use apicache.getIndex() to inspect current cached entries and groups to ensure correct targeting. Warnings
gotcha When using `apicache` with the `compression` middleware, ensure `compression` is applied *before* `apicache` in the middleware chain for `apicache` to cache the compressed response. Older versions might have had issues with header mutation, but v0.8.0 and later addressed this. ↓
fix Ensure `app.use(compression());` comes before `app.use(apicache.middleware('duration'));` or before any route-specific cache middleware.
breaking The injection of `apicache-store` and `apicache-version` headers moved from before cache-injection to response-building from cache. This means middleware interceptors will only detect these headers when a response is actually served from the cache, not when the request is initially processed. ↓
fix Adjust any custom middleware that relies on `apicache` headers to check for their presence during the response phase, specifically when a cache hit occurs.
gotcha Debugging output for apicache, while configurable via `apicache.options({ debug: true })`, is now primarily and preferentially controlled via the `DEBUG` environment variable, specifically `DEBUG=apicache`. ↓
fix For detailed logging, set the environment variable `export DEBUG=apicache` before running your Node.js application instead of relying solely on `options({ debug: true })`.
breaking apicache requires Node.js version 8 or higher. Using it with older Node.js versions will lead to compatibility issues or failures. ↓
fix Upgrade your Node.js environment to version 8 or newer.
gotcha When using `apicache.options()` to configure global settings (like `redisClient` or custom `headers`), ensure you apply it before initializing your `apicache.middleware`. Calling `options` modifies the global `apicache` object. ↓
fix Set global options before creating or using the `middleware` instance: `let cache = apicache.options({ /* ... */ }).middleware;`
Install
npm install apicache yarn add apicache pnpm add apicache Imports
- apicache wrong
const apicache = require('apicache').apicachecorrectimport apicache from 'apicache' - middleware wrong
import { middleware } from 'apicache'correctimport apicache from 'apicache'; let cache = apicache.middleware; - options wrong
import { options } from 'apicache'correctimport apicache from 'apicache'; apicache.options({ ... }) - clear wrong
import { clear } from 'apicache'correctimport apicache from 'apicache'; apicache.clear('target')
Quickstart
import express from 'express';
import apicache from 'apicache';
import redis from 'redis'; // Optional: for Redis integration
const app = express();
// --- Configuration for in-memory cache ---
let cache = apicache.middleware;
// --- Configuration for Redis cache (uncomment to use) ---
// const redisClient = redis.createClient({ url: process.env.REDIS_URL ?? 'redis://localhost:6379' });
// redisClient.on('error', (err) => console.error('Redis Client Error', err));
// redisClient.connect(); // Connect the client
// let cache = apicache.options({ redisClient }).middleware;
// Basic cached route (in-memory or Redis based on config above)
app.get('/api/data', cache('1 minute'), (req, res) => {
console.log('Fetching fresh data for /api/data');
res.json({ timestamp: new Date(), value: Math.random() });
});
// Route to check cache performance and index
app.get('/api/cache/performance', (req, res) => {
res.json(apicache.getPerformance());
});
app.get('/api/cache/index', (req, res) => {
res.json(apicache.getIndex());
});
// Route to manually clear cache (e.g., all entries, or a specific target/group)
app.get('/api/cache/clear/:target?', (req, res) => {
const target = req.params.target || 'all'; // 'all' clears everything if no target is specified
console.log(`Clearing cache for target: ${target}`);
res.json(apicache.clear(target));
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server running on http://localhost:${PORT}`);
console.log('Try visiting http://localhost:3000/api/data multiple times quickly.');
console.log('Then try http://localhost:3000/api/cache/clear');
});