Prisma Redis Caching Middleware
raw JSON →prisma-redis-middleware is a Prisma middleware designed to cache the results of Prisma queries in Redis, significantly improving application performance by reducing database load. It also provides an in-memory LRU cache as a fallback mechanism. The current stable version is 4.8.0, with frequent patch and minor releases, indicating active development and responsiveness to community needs. Key features include fine-grained cache invalidation, support for custom cache keys, persistence with Redis, and the ability to define specific caching rules for individual Prisma models and methods (e.g., `findUnique`, `findMany`, `count`, `aggregate`, `groupBy`). It allows developers to include or exclude certain models or query methods from being cached, and define custom cache times per model, distinguishing it from simpler caching solutions. The middleware internally leverages `async-cache-dedupe` for efficient request deduplication. Developers must provide their own Redis client implementation, such as `ioredis`, which is a common and recommended choice for robust Redis connectivity.
Common errors
error Error: Cannot find module 'ioredis' ↓
ioredis and its types: npm install ioredis @types/ioredis. error TypeError: prisma.$use is not a function ↓
@prisma/client to a version that supports middleware (Prisma 2.x or newer). Ensure new PrismaClient() is called before attempting to apply middleware. error Redis connection error: connect ECONNREFUSED <IP>:<PORT> ↓
REDIS_URL environment variable or explicit options) for correct host, port, and authentication credentials. error TypeScript error: Argument of type '{ models: { model: string; excludeMethods: string[]; }[]; ... }' is not assignable to parameter of type 'Prisma.Middleware'. ↓
import Prisma from 'prisma'; is used to import the Prisma namespace correctly. The createPrismaRedisCache function returns the middleware function, which is then assigned to a variable typed as Prisma.Middleware. Warnings
breaking `prisma-redis-middleware` requires Node.js versions 16.x or 18.x. Older or unsupported Node.js versions may lead to unexpected behavior or runtime errors. ↓
gotcha This middleware requires a separate Redis client library (e.g., `ioredis`) for Redis storage. It does not bundle one. Failing to install and configure an external client will lead to runtime errors when `type: 'redis'` is selected for storage. ↓
gotcha Ensure compatibility between `prisma-redis-middleware` and your `@prisma/client` version. Major Prisma upgrades can introduce breaking changes to the middleware API, potentially requiring an update to this package. ↓
gotcha Proper cache invalidation, especially with options like `referencesTTL`, requires careful configuration. Misconfigured invalidation strategies can result in stale data being served from the cache, leading to data inconsistencies. ↓
gotcha The order of applying Prisma middleware via `prisma.$use()` can impact application behavior. If you use other middleware alongside `prisma-redis-middleware`, their interaction might produce unexpected results. ↓
Install
npm install prisma-redis-middleware yarn add prisma-redis-middleware pnpm add prisma-redis-middleware Imports
- createPrismaRedisCache wrong
const { createPrismaRedisCache } = require('prisma-redis-middleware');correctimport { createPrismaRedisCache } from 'prisma-redis-middleware'; - Prisma wrong
import { Prisma } from '@prisma/client';correctimport Prisma from 'prisma'; - Redis wrong
const Redis = require('ioredis');correctimport Redis from 'ioredis';
Quickstart
import Prisma from "prisma";
import { PrismaClient } from "@prisma/client";
import { createPrismaRedisCache } from "prisma-redis-middleware";
import Redis from "ioredis";
const redis = new Redis(process.env.REDIS_URL || 'redis://localhost:6379'); // Connects to Redis, uses REDIS_URL or default
const prisma = new PrismaClient();
const cacheMiddleware: Prisma.Middleware = createPrismaRedisCache({
models: [
{ model: "User", excludeMethods: ["findMany"] },
{ model: "Post", cacheTime: 180, cacheKey: "article" },
],
storage: { type: "redis", options: { client: redis, invalidation: { referencesTTL: 300 }, log: console } },
cacheTime: 300,
excludeModels: ["Product", "Cart"],
excludeMethods: ["count", "groupBy"],
onHit: (key) => {
console.log("Cache HIT for key:", key);
},
onMiss: (key) => {
console.log("Cache MISS for key:", key);
},
onError: (key, error) => {
console.error("Cache ERROR for key:", key, error);
}
});
prisma.$use(cacheMiddleware);
async function main() {
// Example usage: Caching a 'findUnique' query for a 'User' model
const user = await prisma.user.findUnique({
where: { id: 1 },
});
console.log('Fetched user:', user);
// Example usage: Querying 'Post' model with custom cache time
const posts = await prisma.post.findMany();
console.log('Fetched posts:', posts);
}
main()
.catch((e) => {
console.error(e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
redis.disconnect();
});