Advanced

Como disenar e implementar estrategias de cache con Claude Code

Aprende a disenar e implementar estrategias de cache con Claude Code. Incluye ejemplos de codigo practicos y guia paso a paso.

Ventajas de usar Claude Code para disenar estrategias de cache

Si el cache no se disena adecuadamente, puede provocar la visualizacion de datos obsoletos y el desperdicio de memoria. Claude Code puede analizar los patrones de acceso a datos de tu aplicacion y proponer e implementar la estrategia de cache optima.

Implementacion de cache con Redis

> Implementa una capa de cache usando Redis.
> Con invalidacion de cache, gestion de TTL y patron cache-aside.
// src/lib/cache.ts
import Redis from 'ioredis';

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

interface CacheOptions {
  ttl?: number;      // en segundos
  prefix?: string;
}

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

  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();

Implementacion del patron 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,
    });

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

    return product;
  }
}

Configuracion de headers de cache HTTP

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

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

  // Assets estaticos: cache a largo plazo
  if (path.match(/\.(js|css|png|jpg|svg|woff2)$/)) {
    res.headers.set('Cache-Control', 'public, max-age=31536000, immutable');
  }

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

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

  return res;
}

Cache en memoria (dentro de la aplicacion)

Para datos de tamano reducido, el cache en memoria es efectivo.

// 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 {
    // Verificar limite de tamano
    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();
  }
}

// Usar para datos de acceso frecuente como configuraciones
export const configCache = new MemoryCache(100);

Guia de seleccion de estrategia de cache

Tipo de datosCache recomendadoTTL estimado
Configuracion maestraMemoria + Redis1 hora
Perfil de usuarioRedis10 minutos
Lista de productosRedis + CDN5 minutos
Informacion de sesionRedis24 horas
Assets estaticosCDN1 ano
Respuesta APIHTTP Cache1 minuto

Monitoreo del cache

// Medicion de la tasa de aciertos del cache
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

Con Claude Code puedes disenar e implementar eficientemente estrategias de cache multicapa incluyendo cache Redis, cache HTTP y cache en memoria. Si documentas las politicas de diseno de cache en CLAUDE.md, obtendras una implementacion consistente en todo el proyecto. Para la vision general de la mejora de rendimiento, consulta tambien los consejos para triplicar tu productividad.

Para mas detalles sobre Claude Code, consulta la documentacion oficial de Anthropic. Para mas detalles sobre Redis, consulta la documentacion oficial de Redis.

#Claude Code #caching #Redis #performance #design