Use Arctickey as a cache layer for DrizzleORM queries.
// lib/cache.ts import Redis from 'ioredis'; const redis = new Redis({ host: process.env.ARCTICKEY_HOST, port: parseInt(process.env.ARCTICKEY_PORT || '6379'), password: process.env.ARCTICKEY_PASSWORD, tls: { rejectUnauthorized: false }, }); interface CacheOptions { ttl?: number; tags?: string[]; } export async function cached<T>( key: string, fn: () => Promise<T>, options: CacheOptions = {} ): Promise<T> { const { ttl = 60, tags = [] } = options; const cached = await redis.get(key); if (cached) { return JSON.parse(cached); } const result = await fn(); if (ttl > 0) { await redis.set(key, JSON.stringify(result), 'EX', ttl); } for (const tag of tags) { await redis.sadd(`tag:${tag}`, key); } return result; } export async function invalidateTag(tag: string): Promise<void> { const keys = await redis.smembers(`tag:${tag}`); if (keys.length > 0) { await redis.del(...keys); await redis.del(`tag:${tag}`); } }
// db/queries.ts import { db } from './drizzle'; import { users, posts } from './schema'; import { eq } from 'drizzle-orm'; import { cached, invalidateTag } from '@/lib/cache'; // Cached query export async function getUsers() { return cached( 'users:all', () => db.select().from(users), { ttl: 300, tags: ['users'] } ); } // Cached query with params export async function getUserById(id: string) { return cached( `users:${id}`, () => db.select().from(users).where(eq(users.id, id)), { ttl: 300, tags: ['users', `user:${id}`] } ); } // Mutation with cache invalidation export async function createUser(data: { name: string; email: string }) { const result = await db.insert(users).values(data).returning(); await invalidateTag('users'); return result[0]; }
export async function createPost(data) { const post = await db.insert(posts).values(data).returning(); // Update cache immediately await redis.set(`posts:${post[0].id}`, JSON.stringify(post[0]), 'EX', 300); await invalidateTag('posts'); return post[0]; }
export async function getPost(id: string) { const cached = await redis.get(`posts:${id}`); if (cached) return JSON.parse(cached); const post = await db.select().from(posts).where(eq(posts.id, id)); if (post[0]) { await redis.set(`posts:${id}`, JSON.stringify(post[0]), 'EX', 300); } return post[0]; }
DrizzleORM
Use Arctickey as a cache layer for DrizzleORM queries.
Setup Cache Helper#
// lib/cache.ts import Redis from 'ioredis'; const redis = new Redis({ host: process.env.ARCTICKEY_HOST, port: parseInt(process.env.ARCTICKEY_PORT || '6379'), password: process.env.ARCTICKEY_PASSWORD, tls: { rejectUnauthorized: false }, }); interface CacheOptions { ttl?: number; tags?: string[]; } export async function cached<T>( key: string, fn: () => Promise<T>, options: CacheOptions = {} ): Promise<T> { const { ttl = 60, tags = [] } = options; const cached = await redis.get(key); if (cached) { return JSON.parse(cached); } const result = await fn(); if (ttl > 0) { await redis.set(key, JSON.stringify(result), 'EX', ttl); } for (const tag of tags) { await redis.sadd(`tag:${tag}`, key); } return result; } export async function invalidateTag(tag: string): Promise<void> { const keys = await redis.smembers(`tag:${tag}`); if (keys.length > 0) { await redis.del(...keys); await redis.del(`tag:${tag}`); } }Usage with Drizzle#
// db/queries.ts import { db } from './drizzle'; import { users, posts } from './schema'; import { eq } from 'drizzle-orm'; import { cached, invalidateTag } from '@/lib/cache'; // Cached query export async function getUsers() { return cached( 'users:all', () => db.select().from(users), { ttl: 300, tags: ['users'] } ); } // Cached query with params export async function getUserById(id: string) { return cached( `users:${id}`, () => db.select().from(users).where(eq(users.id, id)), { ttl: 300, tags: ['users', `user:${id}`] } ); } // Mutation with cache invalidation export async function createUser(data: { name: string; email: string }) { const result = await db.insert(users).values(data).returning(); await invalidateTag('users'); return result[0]; }Cache Patterns#
Write-Through Cache#
export async function createPost(data) { const post = await db.insert(posts).values(data).returning(); // Update cache immediately await redis.set(`posts:${post[0].id}`, JSON.stringify(post[0]), 'EX', 300); await invalidateTag('posts'); return post[0]; }Cache-Aside (Lazy Loading)#
export async function getPost(id: string) { const cached = await redis.get(`posts:${id}`); if (cached) return JSON.parse(cached); const post = await db.select().from(posts).where(eq(posts.id, id)); if (post[0]) { await redis.set(`posts:${id}`, JSON.stringify(post[0]), 'EX', 300); } return post[0]; }