Advanced

Cara Mendesain dan Mengimplementasikan Strategi Caching dengan Claude Code

Pelajari cara mendesain dan mengimplementasikan strategi caching menggunakan Claude Code. Dilengkapi contoh kode praktis dan panduan langkah demi langkah.

Keuntungan Menggunakan Claude Code untuk Desain Strategi Cache

Cache yang tidak didesain dengan tepat bisa menyebabkan tampilan data lama atau pemborosan memori. Claude Code bisa menganalisis pola akses data aplikasi dan menyarankan serta mengimplementasikan strategi cache optimal.

Implementasi Redis Cache

> Implementasikan cache layer menggunakan Redis.
> Dengan cache invalidation, manajemen TTL, dan pola cache-aside.
// src/lib/cache.ts
import Redis from 'ioredis';

const redis = new Redis(process.env.REDIS_URL!);

interface CacheOptions {
  ttl?: number;      // Dalam detik
  prefix?: string;
}

export class CacheService {
  private defaultTTL = 300; // 5 menit

  async get<T>(key: string, options?: CacheOptions): Promise<T | null> {
    const fullKey = this.buildKey(key, options?.prefix);
    const data = await redis.get(fullKey);
    if (!data) return null;

    try {
      return JSON.parse(data) as T;
    } catch {
      return null;
    }
  }

  async set<T>(key: string, value: T, options?: CacheOptions): Promise<void> {
    const fullKey = this.buildKey(key, options?.prefix);
    const ttl = options?.ttl ?? this.defaultTTL;

    await redis.setex(fullKey, ttl, JSON.stringify(value));
  }

  async getOrSet<T>(
    key: string,
    fetcher: () => Promise<T>,
    options?: CacheOptions
  ): Promise<T> {
    const cached = await this.get<T>(key, options);
    if (cached !== null) return cached;

    const data = await fetcher();
    await this.set(key, data, options);
    return data;
  }

  async invalidate(key: string, prefix?: string): Promise<void> {
    const fullKey = this.buildKey(key, prefix);
    await redis.del(fullKey);
  }

  async invalidatePattern(pattern: string): Promise<void> {
    const keys = await redis.keys(pattern);
    if (keys.length > 0) {
      await redis.del(...keys);
    }
  }

  private buildKey(key: string, prefix?: string): string {
    return prefix ? `${prefix}:${key}` : key;
  }
}

export const cache = new CacheService();

Implementasi Pola Cache-Aside

// src/services/product-service.ts
import { cache } from '@/lib/cache';
import { prisma } from '@/lib/db';

export class ProductService {
  async getProduct(id: string) {
    return cache.getOrSet(
      `product:${id}`,
      () => prisma.product.findUnique({
        where: { id },
        include: { category: true, reviews: { take: 10 } },
      }),
      { ttl: 600, prefix: 'products' }
    );
  }

  async getPopularProducts(limit = 20) {
    return cache.getOrSet(
      `popular:${limit}`,
      () => prisma.product.findMany({
        orderBy: { salesCount: 'desc' },
        take: limit,
        include: { category: true },
      }),
      { ttl: 300, prefix: 'products' }
    );
  }

  async updateProduct(id: string, data: UpdateProductInput) {
    const product = await prisma.product.update({
      where: { id },
      data,
    });

    // Invalidasi cache terkait
    await cache.invalidate(`product:${id}`, 'products');
    await cache.invalidatePattern('products:popular:*');

    return product;
  }
}

Konfigurasi HTTP Cache Header

// src/middleware.ts
import { NextResponse, NextRequest } from 'next/server';

export function middleware(req: NextRequest) {
  const res = NextResponse.next();
  const path = req.nextUrl.pathname;

  // Aset statis: cache jangka panjang
  if (path.match(/\.(js|css|png|jpg|svg|woff2)$/)) {
    res.headers.set('Cache-Control', 'public, max-age=31536000, immutable');
  }

  // API: tanpa cache
  if (path.startsWith('/api/')) {
    res.headers.set('Cache-Control', 'no-store');
  }

  // Halaman: cache jangka pendek + ISR
  if (!path.startsWith('/api/') && !path.match(/\.[a-z]+$/)) {
    res.headers.set('Cache-Control', 'public, s-maxage=60, stale-while-revalidate=300');
  }

  return res;
}

Memory Cache (Internal Aplikasi)

Untuk data skala kecil, in-memory cache efektif.

// src/lib/memory-cache.ts
interface CacheEntry<T> {
  value: T;
  expiresAt: number;
}

export class MemoryCache {
  private store = new Map<string, CacheEntry<unknown>>();
  private maxSize: number;

  constructor(maxSize = 1000) {
    this.maxSize = maxSize;
  }

  get<T>(key: string): T | null {
    const entry = this.store.get(key);
    if (!entry) return null;

    if (Date.now() > entry.expiresAt) {
      this.store.delete(key);
      return null;
    }

    return entry.value as T;
  }

  set<T>(key: string, value: T, ttlMs: number): void {
    // Pengecekan batas ukuran
    if (this.store.size >= this.maxSize) {
      const firstKey = this.store.keys().next().value;
      if (firstKey) this.store.delete(firstKey);
    }

    this.store.set(key, {
      value,
      expiresAt: Date.now() + ttlMs,
    });
  }

  clear(): void {
    this.store.clear();
  }
}

// Digunakan untuk data yang sering diakses seperti nilai konfigurasi
export const configCache = new MemoryCache(100);

Panduan Pemilihan Strategi Cache

Tipe DataCache yang DirekomendasikanEstimasi TTL
Config MasterMemory + Redis1 jam
Profil UserRedis10 menit
Daftar ProdukRedis + CDN5 menit
Info SesiRedis24 jam
Aset StatisCDN1 tahun
Respons APIHTTP Cache1 menit

Monitoring Cache

// Pengukuran cache hit rate
export class CacheMetrics {
  private hits = 0;
  private misses = 0;

  recordHit() { this.hits++; }
  recordMiss() { this.misses++; }

  getHitRate(): number {
    const total = this.hits + this.misses;
    return total === 0 ? 0 : this.hits / total;
  }

  getStats() {
    return {
      hits: this.hits,
      misses: this.misses,
      hitRate: `${(this.getHitRate() * 100).toFixed(1)}%`,
    };
  }
}

Summary

Dengan Claude Code, strategi cache berlapis seperti Redis cache, HTTP cache, dan memory cache bisa didesain dan diimplementasikan secara efisien. Dengan mendokumentasikan kebijakan desain cache di CLAUDE.md, implementasi yang konsisten di seluruh project bisa didapat. Untuk gambaran umum peningkatan performa, lihat juga Tips Melipatgandakan Produktivitas 3x.

Untuk detail Claude Code, lihat Dokumentasi Resmi Anthropic. Untuk detail Redis, lihat Dokumentasi Resmi Redis.

#Claude Code #caching #Redis #performance #design