Skip to main content
ClaudeWave
leejpsd avatar
leejpsd

nextjs-cache-handler

View on GitHub

Redis cache handler for Next.js 16 — supports both cacheHandler (ISR) & cacheHandlers ('use cache'). Lua-atomic tagging, in-memory fallback, deploy isolation

MCP ServersOfficial Registry5 stars1 forksTypeScriptMITUpdated today
Install in Claude Code / Claude Desktop
Method: NPX · skills
Claude Code CLI
claude mcp add nextjs-cache-handler -- npx -y skills
claude_desktop_config.json (Claude Desktop)
{
  "mcpServers": {
    "nextjs-cache-handler": {
      "command": "npx",
      "args": ["-y", "skills"]
    }
  }
}
1. Run the command above in your terminal (Claude Code), or paste the JSON config into claude_desktop_config.json (Claude Desktop).
2. Replace any <placeholder> values with your API keys or paths.
3. Restart Claude. The MCP server and its tools appear automatically.
Use cases

MCP Servers overview

# @leejpsd/nextjs-cache-handler

[![npm](https://img.shields.io/npm/v/@leejpsd/nextjs-cache-handler.svg)](https://www.npmjs.com/package/@leejpsd/nextjs-cache-handler)
[![license](https://img.shields.io/npm/l/@leejpsd/nextjs-cache-handler.svg)](./LICENSE)

> **`v0.3.0`** — install with
> `npm install @leejpsd/nextjs-cache-handler`. Production-validated against
> AWS ECS Fargate with multi-instance Redis (v0.1: 24h live-traffic soak;
> v0.3: fresh multi-instance verification incl. a live Redis-reboot drill
> with zero 5xx — see
> [`docs/staging-verification-2026-08-01.md`](./docs/staging-verification-2026-08-01.md)).
>
> v0.3 adds: **Next.js 15 support** (ISR handler), **reconnect with
> exponential backoff** (no more permanent memory-only latch), **request-scoped
> GET deduplication**, transparent **gzip/brotli compression**, **Redis
> Sentinel** support, a built-in **OpenTelemetry emitter** at `/otel`, and an
> LRU-bounded memory fallback.

## 🤖 For AI agents

Working with Claude Code / Codex / Cursor? Give your agent this URL and it
will install and wire everything (version detection, wrapper files,
next.config patch, verification):

```
https://raw.githubusercontent.com/leejpsd/nextjs-cache-handler/main/setup-instructions/setup.md
```

An agent skill with decision tables, invalidation semantics, and a
troubleshooting playbook ships in the package (`AGENTS.md`,
`skills/nextjs-redis-cache/SKILL.md`) and via
`npx skills add leejpsd/nextjs-cache-handler`.

For cache operations from your agent (health, tag state, safe invalidation),
the companion MCP server is on the official registry as
`io.github.leejpsd/nextjs-cache-handler-mcp` — or one command:
`npx nextjs-cache-handler init --yes` wires handlers, rules, and `.mcp.json` together.

---

The Redis cache handler for **Next.js 15/16** that ships **both** `cacheHandler`
(ISR / Pages Router) **and** `cacheHandlers` (`'use cache'` directive,
`cacheComponents: true`) — the area where
[`@fortedigital/nextjs-cache-handler`](https://github.com/fortedigital/nextjs-cache-handler)
currently lists "Help needed".

```ts
// next.config.ts
const nextConfig = {
  cacheComponents: true,
  cacheHandler: require.resolve("./cache-incremental.cjs"),
  cacheHandlers: { default: require.resolve("./cache-components.cjs") },
};
```

```js
// cache-components.cjs
const { createCacheComponentsHandler } = require("@leejpsd/nextjs-cache-handler/cache-components");
module.exports = createCacheComponentsHandler({
  client: { type: "redis", url: process.env.REDIS_URL },
  buildNamespace: process.env.DEPLOYMENT_VERSION, // auto-isolates deploys
});
```

That's it. `'use cache'`, `revalidateTag`, `updateTag`, `cacheLife` all work.

---

## Why this exists

Next.js 16 split caching into two handler interfaces:

| Option | Used by | Methods |
|---|---|---|
| `cacheHandler` (singular) | Pages Router ISR, on-demand revalidation | `get`, `set`, `revalidateTag`, `resetRequestCache` |
| `cacheHandlers` (plural) | `'use cache'` directive, `cacheComponents: true` | `get`, `set`, `refreshTags`, `getExpiration`, `updateTags` |

As of 2026-05, the leading OSS Redis handler `@fortedigital/nextjs-cache-handler@3.2.0`
declares `peerDependencies.next: ">=16.1.5"` but the README marks the new
plural interface as ❌ **"Not yet supported - Help needed"**:

> 📅 **Compatibility matrix re-verified 2026-07-31** (from each project's
> published README/registry metadata). The OSS Next.js cache
> handler ecosystem moves quickly — please verify
> [`@fortedigital`](https://github.com/fortedigital/nextjs-cache-handler#compatibility)
> and
> [`nextjs-turbo-redis-cache`](https://github.com/trieb-work/nextjs-turbo-redis-cache#features)
> directly before relying on this comparison.

| Feature | this (0.3.0) | @fortedigital 3.2.1 | nextjs-turbo-redis-cache 1.15 |
|---|---|---|---|
| `cacheHandlers` config (plural) | ✅ | ❌ Help needed | ✅ since 1.11 |
| `'use cache'` directive | ✅ | ❌ Help needed | ✅ since 1.11 |
| `'use cache: remote'` | ✅ default handler (dedicated multi-tier: roadmap) | ❌ Help needed | partial |
| `'use cache: private'` | n/a (uncustomizable) | n/a | n/a |
| `cacheComponents: true` | ✅ | ❌ Help needed | ✅ |
| Build-phase skip (`PHASE_PRODUCTION_BUILD`) | ✅ | ✅ (singular only) | ✅ |
| Auto deploy isolation | ✅ `BUILD_NAMESPACE` env-resolved | manual | ✅ `BUILD_ID` since 1.13 |
| Lua-atomic SET+tag | ✅ Lua scripts | partial (MULTI) | partial |
| AbortSignal timeout | ✅ per-op | ✅ Proxy-wrapped | ❌ |
| Redis Cluster | ✅ (cluster adapter, see Production checklist) | ✅ | ✅ |
| ioredis support | ✅ | ✅ | ✅ |
| In-memory fallback (TTL-aware) | ✅ | partial | ✅ L1 + Redis L2 |
| Next 15 support (ISR handler) | ✅ `>=15.0.0` | ✅ (legacy 2.x line) | ✅ `>=15.0.3` |
| Request-scoped GET dedup | ✅ | ❌ | ✅ |
| Built-in value compression | ✅ gzip/brotli option | example only | example only |
| Redis Sentinel | ✅ (local failover drill) | ❌ | ❌ |
| OpenTelemetry | ✅ built-in `/otel` emitter + `onMetric` hook | ❌ | ❌ |
| Reconnect strategy | ✅ exponential backoff | client-level | error-threshold restart |
| Live-traffic dogfood (24h+) | ✅ AWS ECS Fargate | not published | not published |

PR [#207](https://github.com/fortedigital/nextjs-cache-handler/pull/207) on
`@fortedigital` (their `cacheHandlers` attempt) was held up in review over
`PHASE_PRODUCTION_BUILD` handling — which this package has from the start.

---

## Quick start

### Install

```bash
npm install @leejpsd/nextjs-cache-handler redis
# or
npm install @leejpsd/nextjs-cache-handler ioredis
```

`redis` and `ioredis` are optional peer dependencies — install whichever
client you use. Both can be present.

### Wire up

Two CommonJS wrapper files in your project root (Next.js's
`require.resolve` pattern doesn't accept ESM directly):

```js
// cache-components.cjs
const { createCacheComponentsHandler } = require("@leejpsd/nextjs-cache-handler/cache-components");
module.exports = createCacheComponentsHandler({
  client: { type: "redis", url: process.env.REDIS_URL },
  buildNamespace: process.env.DEPLOYMENT_VERSION,
  abortTimeoutMs: 1500,
});
```

```js
// cache-incremental.cjs
const { createIncrementalCacheHandler } = require("@leejpsd/nextjs-cache-handler/incremental");
module.exports = createIncrementalCacheHandler({
  client: { type: "redis", url: process.env.REDIS_URL },
  buildNamespace: process.env.DEPLOYMENT_VERSION,
  abortTimeoutMs: 1500,
});
```

```ts
// next.config.ts
import path from "path";
import type { NextConfig } from "next";

const enabled = !!process.env.REDIS_URL && process.env.DISABLE_REDIS_CACHE_HANDLER !== "true";

const nextConfig: NextConfig = {
  output: "standalone",
  outputFileTracingRoot: path.join(__dirname),
  cacheComponents: true,
  deploymentId: process.env.DEPLOYMENT_VERSION,
  generateBuildId: async () => process.env.DEPLOYMENT_VERSION ?? "dev-build",
  cacheMaxMemorySize: 0, // delegate everything to the Redis handler
  cacheHandler: enabled ? require.resolve("./cache-incremental.cjs") : undefined,
  cacheHandlers: enabled ? { default: require.resolve("./cache-components.cjs") } : {},
};
export default nextConfig;
```

### Use in your code

```tsx
// app/blog/page.tsx
import { cacheLife, cacheTag, revalidateTag } from "next/cache";

async function getPosts() {
  "use cache";
  cacheLife("hours");
  cacheTag("posts");
  return await db.post.findMany();
}

// Server Action — invalidate
async function publishPost(formData: FormData) {
  "use server";
  await db.post.create({ data: Object.fromEntries(formData) });
  revalidateTag("posts", "max");
}

export default async function Page() {
  const posts = await getPosts();
  return <ul>{posts.map((p) => <li key={p.id}>{p.title}</li>)}</ul>;
}
```

---

## Configuration reference

```ts
interface CacheHandlerOptions {
  client: RedisClientFactory | RedisClientConfig;
  keyPrefix?: string;             // default: "next-cache:" / "next-incremental:"
  buildNamespace?: string | (() => string);  // default: env DEPLOYMENT_VERSION || GIT_HASH || "unversioned"
  abortTimeoutMs?: number;        // default: 1500
  fallback?: "auto" | "always" | "never";    // default: "auto"
  staleWhileRevalidate?: boolean; // default: true (cache-components only)
  singleFlight?: boolean;         // default: false — see "Single-flight refresh lock" below
  singleFlightLockTtlSec?: number; // default: 10
  isBuildPhase?: () => boolean;   // override PHASE_PRODUCTION_BUILD detection
  hashTag?: boolean;              // default: false (set true on Redis Cluster)
  memoryMaxEntries?: number;      // default: 1000 — LRU cap for the in-memory fallback
  compression?: "gzip" | "brotli"; // default: off — transparent value compression (node:zlib)
  onMetric?: (event: MetricEvent) => void;
  logger?: Logger;
}

type RedisClientConfig =
  | { type: "redis";    url: string; password?: string; tls?: boolean; connectTimeout?: number }
  | { type: "ioredis";  url: string; password?: string; tls?: boolean; connectTimeout?: number }
  | { type: "cluster";  nodes: { host: string; port: number }[]; password?: string; tls?: boolean }
  | { type: "sentinel"; sentinels: { host: string; port: number }[]; name: string;
      password?: string; sentinelPassword?: string; tls?: boolean; connectTimeout?: number };
```

Full reference: [`docs/api.md`](./docs/api.md).

---

## Production checklist

- [ ] **`DEPLOYMENT_VERSION` env injected at runtime** — every entry key is
      prefixed with this so old prerender HTML can't bleed across deploys.
      For Docker, set `ENV DEPLOYMENT_VERSION=...` in your **runner** stage,
      not just the builder. (See [`docs/build-phase.md`](./docs/build-phase.md).)
- [ ] **`cacheMaxMemorySize: 0`** — turn off Next's local LRU so multi-instance
      reads always hit Redis (or the explicit memory fallback).
- [ ] **`outputFileTracingRoot` pinned** — required for `output: "standalone"`
      to avoid static-chunk-404 issues during a deploy.
- [ ] **`abortTimeoutMs: 1500`** (default) — protects against 

What people ask about nextjs-cache-handler

What is leejpsd/nextjs-cache-handler?

+

leejpsd/nextjs-cache-handler is mcp servers for the Claude AI ecosystem. Redis cache handler for Next.js 16 — supports both cacheHandler (ISR) & cacheHandlers ('use cache'). Lua-atomic tagging, in-memory fallback, deploy isolation It has 5 GitHub stars and was last updated today.

How do I install nextjs-cache-handler?

+

You can install nextjs-cache-handler by cloning the repository (https://github.com/leejpsd/nextjs-cache-handler) or following the README instructions on GitHub. ClaudeWave also provides quick install blocks on this page.

Is leejpsd/nextjs-cache-handler safe to use?

+

leejpsd/nextjs-cache-handler has not been audited yet by our security agent. Review the original repository on GitHub before using it in production.

Who maintains leejpsd/nextjs-cache-handler?

+

leejpsd/nextjs-cache-handler is maintained by leejpsd. The last recorded GitHub activity is from today, with 0 open issues.

Are there alternatives to nextjs-cache-handler?

+

Yes. On ClaudeWave you can browse similar mcp servers at /categories/mcp, sorted by popularity or recent activity.

Deploy nextjs-cache-handler to your cloud

Ship this repo to production in minutes. Each platform spins up its own environment with editable env vars.

Maintain this repo? Add a badge to your README

Drop the badge into your GitHub README to show it's tracked on ClaudeWave. Each badge links back to this page and reflects the live Trust Score.

Featured on ClaudeWave: leejpsd/nextjs-cache-handler
[![Featured on ClaudeWave](https://claudewave.com/api/badge/leejpsd-nextjs-cache-handler)](https://claudewave.com/repo/leejpsd-nextjs-cache-handler)
<a href="https://claudewave.com/repo/leejpsd-nextjs-cache-handler"><img src="https://claudewave.com/api/badge/leejpsd-nextjs-cache-handler" alt="Featured on ClaudeWave: leejpsd/nextjs-cache-handler" width="320" height="64" /></a>

More MCP Servers

nextjs-cache-handler alternatives