// Short TTL for frequently changing dataawait redis.setex('stock:product123', 30, '42');
// Long TTL for static contentawait redis.setex('footer:html', 86400, footerHtml);
// No TTL for critical data (manual invalidation)await redis.set('config:features', JSON.stringify(features));
Caching with Arctickey
Arctickey is perfect for application caching — reduce database load, speed up API responses, and improve user experience.
Why Use Redis for Caching?#
Basic Caching Pattern#
import Redis from 'ioredis'; const redis = new Redis('rediss://:YOUR_PASSWORD@YOUR_INSTANCE.eu.arctickey.com:6379'); async function getCachedData(key: string, fetchFn: () => Promise<any>, ttlSeconds = 300) { // Try cache first const cached = await redis.get(key); if (cached) { return JSON.parse(cached); } // Fetch fresh data const data = await fetchFn(); // Store in cache with TTL await redis.setex(key, ttlSeconds, JSON.stringify(data)); return data; } // Usage const user = await getCachedData( `user:${userId}`, () => db.users.findById(userId), 600 // 10 minutes );Cache-Aside Pattern#
The most common pattern — check cache, fetch if missing, store result:
async function getProduct(id: string) { const cacheKey = `product:${id}`; // 1. Check cache const cached = await redis.get(cacheKey); if (cached) return JSON.parse(cached); // 2. Cache miss - fetch from database const product = await db.products.findById(id); if (!product) return null; // 3. Store in cache await redis.setex(cacheKey, 3600, JSON.stringify(product)); return product; }Write-Through Pattern#
Update cache and database together:
async function updateProduct(id: string, data: ProductData) { // Update database const product = await db.products.update(id, data); // Update cache immediately await redis.setex(`product:${id}`, 3600, JSON.stringify(product)); return product; }TTL Strategies#
Choose TTL based on data characteristics:
// Short TTL for frequently changing data await redis.setex('stock:product123', 30, '42'); // Long TTL for static content await redis.setex('footer:html', 86400, footerHtml); // No TTL for critical data (manual invalidation) await redis.set('config:features', JSON.stringify(features));Cache Invalidation#
Delete on Update#
async function updateUser(id: string, data: UserData) { await db.users.update(id, data); await redis.del(`user:${id}`); }Pattern-Based Invalidation#
// Invalidate all product caches const keys = await redis.keys('product:*'); if (keys.length > 0) { await redis.del(...keys); }Tag-Based Invalidation#
// Store tags with cached items await redis.sadd('tag:electronics', 'product:123', 'product:456'); // Invalidate by tag const keys = await redis.smembers('tag:electronics'); if (keys.length > 0) { await redis.del(...keys); await redis.del('tag:electronics'); }Next.js Data Cache#
// app/api/products/route.ts import { unstable_cache } from 'next/cache'; const getProducts = unstable_cache( async () => { return await db.products.findMany(); }, ['products'], { revalidate: 60 } // Revalidate every 60 seconds );Best Practices#
entity:id:fieldformat