Caching Configuration

Redis caching setup for Portfolio OS

Caching Configuration

Configure Redis caching for optimal performance.

Upstash Redis Setup

1

Create Redis Database

  1. Go to upstash.com
  2. Click "Create Database"
  3. Choose region closest to your deployment
2

Get Credentials

Copy REST URL and Token from database details

3

Configure Environment

# apps/site/.env.local
UPSTASH_REDIS_REST_URL=https://your-redis.upstash.io
UPSTASH_REDIS_REST_TOKEN=your-token-here

Cache Implementation

// packages/lib/src/cache/redis.ts
import { Redis } from '@upstash/redis'

const redis = new Redis({
  url: process.env.UPSTASH_REDIS_REST_URL!,
  token: process.env.UPSTASH_REDIS_REST_TOKEN!,
})

export async function getCached<T>(
  key: string,
  fetcher: () => Promise<T>,
  ttl: number = 3600
): Promise<T> {
  // Try cache
  const cached = await redis.get<T>(key)
  if (cached) return cached
  
  // Fetch and cache
  const data = await fetcher()
  await redis.setex(key, ttl, JSON.stringify(data))
  
  return data
}

export async function invalidateCache(pattern: string) {
  const keys = await redis.keys(pattern)
  if (keys.length > 0) {
    await redis.del(...keys)
  }
}

Usage

import { getCached } from '@mindware-blog/lib/cache'

// Cache blog posts for 1 hour
const posts = await getCached(
  'blog:posts:all',
  () => getAllPosts(),
  3600
)

// Cache single post for 2 hours
const post = await getCached(
  `blog:post:${slug}`,
  () => getPostBySlug(slug),
  7200
)

Cache Strategies

ContentTTLStrategy
Blog posts list1 hourTime-based
Single post2 hoursTime-based
Static pages24 hoursTime-based
API responses15 minTime-based

Cache Invalidation

Manual Invalidation

import { invalidateCache } from '@mindware-blog/lib/cache'

// Invalidate all blog posts
await invalidateCache('blog:*')

// Invalidate specific post
await invalidateCache(`blog:post:${slug}`)

Webhook Invalidation

// apps/site/app/api/webhooks/invalidate/route.ts
import { invalidateCache } from '@mindware-blog/lib/cache'
import { revalidatePath } from 'next/cache'

export async function POST(request: Request) {
  const { pattern } = await request.json()
  
  await invalidateCache(pattern)
  revalidatePath('/blog')
  
  return new Response('OK')
}

Monitoring

Check cache performance:

// Get cache stats
const stats = {
  hits: await redis.get('stats:cache:hits'),
  misses: await redis.get('stats:cache:misses'),
  hitRate: hits / (hits + misses)
}

Next Steps