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!