prisma-extension-redis
provides seamless integration with Prisma and Redis/Dragonfly databases, offering efficient caching mechanisms to improve data access times and overall application performance.
🚀 If prisma-extension-redis
proves helpful, consider giving it a star! ⭐ Star Me!
You can install prisma-extension-redis
using your preferred package manager:
Using npm:
npm install prisma-extension-redis
Using yarn:
yarn add prisma-extension-redis
Using pnpm:
pnpm add prisma-extension-redis
Using bun:
bun add prisma-extension-redis
Before setting up caching, initialize your Prisma client, Redis client config, and logger:
import pino from 'pino';
import { PrismaClient } from '@prisma/client';
import { Redis } from 'iovalkey';
import {SuperJSON} from 'superjson';
import {
CacheCase,
PrismaExtensionRedis,
type AutoCacheConfig,
type CacheConfig,
} from 'prisma-extension-redis';
// Prisma Client
const prisma = new PrismaClient();
// Redis client config
const client = {
host: process.env.REDIS_HOST_NAME, // Redis host
port: process.env.REDIS_PORT, // Redis port
};
// Create a logger using pino (optional)
const logger = pino();
auto
settings enable automated caching for read operations with flexible customization.
const auto: AutoCacheConfig = {
excludedModels: ['Post'], // Models excluded from auto-caching
excludedOperations: ['findFirst', 'count', 'findMany'], // Operations excluded from auto-caching
models: [
{
model: 'User', // Model-specific auto-cache settings
excludedOperations: ['count'], // Operations to exclude
ttl: 10, // Time-to-live (TTL) for cache in seconds
stale: 5, // Stale time in seconds
},
],
ttl: 30, // Default TTL for cache in seconds
};
Note:
- Excluded operations and models will not benefit from auto-caching.
- Use
ttl
andstale
values to define caching duration.
The cache client configuration is necessary to enable caching, either automatically or manually.
const config: CacheConfig = {
ttl: 60, // Default Time-to-live for caching in seconds
stale: 30, // Default Stale time after ttl in seconds
auto, // Auto-caching options (configured above)
logger, // Logger for cache events (configured above)
transformer: {
// Custom serialize and deserialize function for additional functionality if required
deserialize: data => SuperJSON.parse(data),
serialize: data => SuperJSON.stringify(data),
},
type: 'JSON', // Redis cache type, whether you prefer the data to be stored as JSON or STRING in Redis
cacheKey: { // Inbuilt cache key configuration
case: CacheCase.SNAKE_CASE, // Select a cache case conversion option for generated keys from CacheCase
delimiter: '*', // Delimiter for keys (default value: ':')
prefix: 'awesomeness', // Cache key prefix (default value: 'prisma')
},
};
Note: Cache case conversion strips all non alpha numeric characters
Now, extend your Prisma client with caching capabilities using prisma-extension-redis
:
const extendedPrisma = prisma.$extends(
PrismaExtensionRedis({ config, client })
);
With auto-caching, read operations (e.g., findUnique
, findMany
) are cached automatically based on the defined configuration.
Basic Example:
// Cached automatically based on auto-cache settings
extendedPrisma.user.findUnique({
where: { id: userId },
});
// Manually enable cache for a query
extendedPrisma.user.findUnique({
where: { id: userId },
cache: true, // Toggle caching on
});
// Disable cache for specific query
extendedPrisma.user.findFirst({
where: { id: userId },
cache: false, // Toggle caching off
});
Note:
- If
auto-cache
is set tofalse
andcache
is set totrue
for the query, the default values from the cache configuration will be applied. - If
cache
is set tofalse
andauto-cache
is set totrue
, the query will not be cached.
For greater control over caching, generate custom cache keys and TTL settings.
Example with Custom Cache Key:
const customKey = extendedPrisma.getKey({ params: [{ prisma: 'User' }, { id: userId }] });
extendedPrisma.user.findUnique({
where: { id: userId },
cache: { ttl: 5, key: customKey }, // Custom TTL and cache key
});
Cache invalidation ensures data consistency by removing or updating cached data when changes occur in the database.
Example of Cache Invalidation:
// Invalidate cache when updating a user's information
extendedPrisma.user.update({
where: { id: userId },
data: { username: newUsername },
uncache: {
uncacheKeys: [
extendedPrisma.getKey({ params: [{ prisma: 'User' }, { id: userId }] }), // Specific key to invalidate
extendedPrisma.getKeyPattern({ params: [{ prisma: '*' }, { id: userId }]}), // Pattern for wildcard invalidation
extendedPrisma.getKeyPattern({ params: [{ prisma: 'Post' }, { id: userId }, { glob: '*' }]}), // Use glob for more complex patterns
],
hasPattern: true, // Use pattern matching for invalidation
},
});
Explanation of Cache Invalidation:
-
uncacheKeys
: Specifies the keys or patterns to be invalidated. -
hasPattern
: Indicates if wildcard patterns are used for key matching.
- Specifies how long (in seconds) a cached entry should remain before expiring.
- Default TTL: Used when no specific TTL is provided for a query.
- After the TTL expires, stale time defines how long expired data can still be used while refreshing data in the background.
- This ensures that users experience minimal latency even when data is being updated.
-
getKey
: Generates a unique key for caching queries from provided key context parameters. -
getAutoKey
: Generates a unique key for auto-caching queries, based on query parameters. -
getKeyPattern
: Creates patterns for more complex invalidation scenarios, using wildcards.
- Auto-Caching: Automatically cache read operations, reducing redundant queries and improving performance.
- Selective Caching: Customize which queries to cache, how long to cache them, and whether to cache them at all.
- Efficient Invalidation: Keep cached data up-to-date by selectively invalidating caches when updates or deletions occur.
- Granular Control: Easily toggle caching on or off for individual queries as needed.
- Logger Support: Integrate logging to monitor cache hits, misses, and invalidations for easier debugging and optimization.
- Ensure you have a running Redis or Dragonfly instance. If using Redis,
Redis.JSON
must be enabled to use JSON type cache (by default, it is enabled in Dragonfly).
-
iovalkey
package is used for Redis connectivity. -
micromatch
is used for patter matching for keys. -
object-code
is used for generating unique hash in auto-caching keys. -
lodash-es
is used for CacheCase logic in key management.
prisma-extension-redis
offers an efficient and powerful way to manage caching in Prisma-based applications. By leveraging both automatic and custom caching, you can optimize your application's performance while maintaining data consistency.
Upgrade to prisma-extension-redis
for an optimized caching strategy and contribute to its growth by starring the repository if you find it useful!