Transparent query cache for Prisma — intercepts find* calls, caches results, and auto-invalidates on create/update/delete. Driver-agnostic: plug in Bun Redis, ioredis, or in-memory.
bun add @stratapkg/cachePick a driver:
bun add @stratapkg/cache # includes in-memory driverFor Redis via Bun:
# Bun.redis is built-in, no extra package neededFor ioredis:
bun add ioredisimport { PrismaClient } from './generated/client'
import { withCache } from '@stratapkg/cache'
import { BunRedisDriver } from '@stratapkg/cache/bun'
const redis = new Bun.RedisClient('redis://localhost:6379')
const prisma = new PrismaClient({ adapter })
.$extends(withCache({
driver: new BunRedisDriver(redis),
ttl: {
user: 60, // seconds per model
article: 300,
'*': 10, // default
},
}))| Import | Requires |
|---|---|
@stratapkg/cache/bun |
Bun built-in Redis |
@stratapkg/cache/ioredis |
ioredis package |
@stratapkg/cache/memory |
nothing |
// cached after first call
const user = await prisma.user.findUnique({ where: { id: 1 } })Cache key for findUnique/findFirst — model:id. For findMany — hash of the full args object.
// cache for user:1 is dropped automatically
await prisma.user.update({ where: { id: 1 }, data: { name: 'Alice' } })create/update/upsert/delete/deleteMany/updateMany always invalidate relevant model cache.
await prisma.$cache.flush('user') // flush model
await prisma.$cache.flushAll() // flush everythingconst result = await prisma.$queryRaw`SELECT ...`
// with explicit TTL:
const result = await prisma.$queryRawCached(
Prisma.sql`SELECT ...`,
{ ttl: 120 }
)Implement the CacheDriver interface:
interface CacheDriver {
get(key: string): Promise<string | null>
set(key: string, value: string, ttl?: number): Promise<void>
del(key: string): Promise<void>
flush(pattern: string): Promise<void>
}- Prisma >= 7.0
- Any Prisma adapter
MIT