One Redis-backed cache for a Next.js 16+ app, safe through a Redis outage: pages, route handlers
and "use cache: remote" shared across every instance, and "use cache" in each instance's
memory by default, with revalidation shared across all of them.
Important
16.4.3 is a major release under a patch number. The version follows Next.js, so it is
numbered 16.4.3 to match Next.js 16.4.3, but it reworks the handler: withCache, a new page-cache
key layout (the page cache starts cold on upgrade), memory limits, deployment-ID scoping and
ElastiCache IAM. 16.4.2 setups keep working with deprecation warnings, and ^16.4.2 installs get
it automatically. Read Upgrading from 16.4.2 before you deploy.
-
Install the release for your Next.js minor, pinned exact. For Next 16.4.x:
npm install --save-exact @mrjasonroy/cache-components-cache-handler@16.4
@16.4picks the newest 16.4.x and--save-exactpins it. Needs Node.js 22.3+. -
Wrap your config:
// next.config.mjs import { withCache } from "@mrjasonroy/cache-components-cache-handler"; export default withCache({ cacheComponents: true });
-
Pick your setup:
Setup What to do Local dev, CI, previews, one instance Nothing. Without REDIS_URLeverything stays in memory.Redis or Valkey Set REDIS_URL=redis://cache:6379on the running app. InstallationAWS ElastiCache, Serverless or cluster mode disabled Set ELASTICACHE_ENDPOINTandELASTICACHE_AUTH_TOKEN, or the IAM variables. AWS ElastiCacheAWS ElastiCache, cluster mode enabled (with or without IAM) Your own Clusterin custom handler files. Redis Cluster, IAM on your own clientYour own client (Sentinel, other ioredis options or timeouts) Custom handlers Upgrading from 16.4.2 Migrating
Then keep writing "use cache", cacheTag and revalidateTag as Next documents them
(examples).
Setting it up with a coding agent? Paste the prompt in docs/agent-setup.md into Claude Code, Cursor or similar.
The package version follows Next.js. A range such as ^16.4.3 would also accept the 16.5
releases, which remove the APIs deprecated in 16.4.3, so pin it and upgrade the two together
(why). ioredis is installed with the package as an optional
dependency (unless optionals are skipped).
- Pages and route handlers (and cached
fetch) stored in Redis, shared by every instance. Prerendered pages are served from the build output after a restart. - Next's directives, one to one.
"use cache: remote"entries live in Redis, shared by every instance. Plain"use cache"stays in each instance's memory, with tag invalidation shared through Redis; setuseCache: "redis"to share it too."use cache: private"is Next's own and never reaches a handler. - Revalidation across instances.
revalidateTag,updateTagandrevalidatePathreach every instance and every handler. - Redis outage safety. A request never fails because of the cache. Commands time out after 1 s, and while Redis is down the app serves from per-instance memory.
- Entries scoped by build, so a deploy never serves the previous build's pages.
next buildnever connects to Redis.
How it works has the details.
Runtime settings come from the environment of the running app. The main variables:
| Variable | Meaning |
|---|---|
REDIS_URL (or VALKEY_URL) |
redis:// or rediss:// URL. Unset → memory only. |
ELASTICACHE_ENDPOINT, ELASTICACHE_AUTH_TOKEN |
ElastiCache host form, TLS on. For IAM, see IAM authentication. |
CACHE_KEY_PREFIX |
Prefix for every key (default nextjs:). |
CACHE_REDIS=off |
Memory everywhere, even with a URL set. |
CACHE_DEBUG=1 |
Log hits, misses, writes and state changes. |
The installation guide has the full table. There are no variables for timeouts or TTLs; for those, or your own client, see Custom handlers.
withCache(nextConfig, options?) takes three options:
| Option | Default | What it does |
|---|---|---|
pages |
true |
Also handle pages, route handlers and cached fetch (cacheHandler). false leaves them to Next. |
useCache |
"memory" |
"redis" stores plain "use cache" values in Redis too, so instances of the same build share them. handlers.default overrides it. |
handlers |
built-in files | { page?, default?, remote? }: paths to your own handler files. |
memory |
{ heapPercent: 10 } |
The in-process cache budget. Not seen by a standalone server.js: use the CACHE_MEMORY_* variables there. See Memory. |
withCache throws if the config already sets cacheHandlers, or cacheHandler unless
pages: false. Use handlers instead. The API reference
has the details.
Redis 6.2+ or any Valkey, with Lua scripting allowed (revalidations use ZADD GT and a
single-key script). CI runs Redis 7 and Valkey 8, a production-build e2e matrix (memory, Redis,
Valkey, ElastiCache with TLS and an auth token) and an outage suite. Every PR that changes the
package also runs Next.js's own caching e2e suites, with two instances sharing Redis, and fails
on any regression against plain next start. ElastiCache IAM is tested by hand against a real
ElastiCache Serverless cache before each release.
How it's tested has the details and known limits.
- Installation & Setup
- Usage Examples
- How it works: tag coordination, pages and route handlers, Redis outages
- Operations: flushing, closing, logging
- Custom handlers: your own client and
CacheOptions - Redis Configuration: connections, key layout, sizing
- API Reference: every export, including the deprecated ones
- Migrating
- Changelog and releases
git clone https://github.com/mrjasonroy/cache-components-cache-handler
cd cache-components-cache-handler
pnpm install
pnpm build
pnpm testSee docs/development.md for the test lanes and release process. AI agents start with CLAUDE.md; humans with CONTRIBUTING.md.
MIT © Jason Roy