Redis with Claude Code
Learn about redis using Claude Code. Practical tips and code examples included.
Redis キャッシュの重要性
Redisはインメモリデータストアとして、キャッシュ、セッション管理、リアルタイム処理に広く使われています。Claude Codeを使えば、適切なキャッシュ戦略を設計し効率的に実装できます。
基本的なキャッシュ層
import { Redis } from "ioredis";
const redis = new Redis(process.env.REDIS_URL!);
class CacheService {
private redis: Redis;
private defaultTTL: number;
constructor(redis: Redis, defaultTTL = 300) {
this.redis = redis;
this.defaultTTL = defaultTTL;
}
async get<T>(key: string): Promise<T | null> {
const data = await this.redis.get(key);
if (!data) return null;
try {
return JSON.parse(data) as T;
} catch {
return null;
}
}
async set<T>(key: string, value: T, ttl?: number): Promise<void> {
const serialized = JSON.stringify(value);
await this.redis.set(key, serialized, "EX", ttl ?? this.defaultTTL);
}
async delete(key: string): Promise<void> {
await this.redis.del(key);
}
async deletePattern(pattern: string): Promise<void> {
const keys = await this.redis.keys(pattern);
if (keys.length > 0) {
await this.redis.del(...keys);
}
}
}
const cache = new CacheService(redis);
Cache-Aside パターン
async function getPostById(id: string): Promise<Post | null> {
const cacheKey = `post:${id}`;
// 1. キャッシュから取得
const cached = await cache.get<Post>(cacheKey);
if (cached) {
return cached;
}
// 2. DBから取得
const post = await prisma.post.findUnique({
where: { id },
include: { author: true, categories: true },
});
if (!post) return null;
// 3. キャッシュに保存(5分)
await cache.set(cacheKey, post, 300);
return post;
}
// 更新時のキャッシュ無効化
async function updatePost(id: string, data: Partial<Post>) {
const updated = await prisma.post.update({
where: { id },
data,
});
// 関連するキャッシュを無効化
await cache.delete(`post:${id}`);
await cache.deletePattern("posts:list:*");
return updated;
}
リスト結果のキャッシュ
async function getPostsList(params: {
page: number;
category?: string;
}): Promise<PaginatedResult<Post>> {
const cacheKey = `posts:list:${params.page}:${params.category || "all"}`;
const cached = await cache.get<PaginatedResult<Post>>(cacheKey);
if (cached) return cached;
const result = await fetchPostsFromDB(params);
// リスト結果は短めのTTL(1分)
await cache.set(cacheKey, result, 60);
return result;
}
キャッシュデコレータ
function Cacheable(ttl: number = 300) {
return function (
target: any,
propertyKey: string,
descriptor: PropertyDescriptor
) {
const originalMethod = descriptor.value;
descriptor.value = async function (...args: any[]) {
const cacheKey = `${target.constructor.name}:${propertyKey}:${JSON.stringify(args)}`;
const cached = await cache.get(cacheKey);
if (cached) return cached;
const result = await originalMethod.apply(this, args);
await cache.set(cacheKey, result, ttl);
return result;
};
return descriptor;
};
}
class PostService {
@Cacheable(300)
async getById(id: string) {
return prisma.post.findUnique({ where: { id } });
}
@Cacheable(60)
async getPopular(limit: number = 10) {
return prisma.post.findMany({
where: { published: true },
orderBy: { viewCount: "desc" },
take: limit,
});
}
}
セッション管理
import session from "express-session";
import RedisStore from "connect-redis";
const redisStore = new RedisStore({
client: redis,
prefix: "sess:",
ttl: 86400, // 24時間
});
app.use(
session({
store: redisStore,
secret: process.env.SESSION_SECRET!,
resave: false,
saveUninitialized: false,
cookie: {
secure: process.env.NODE_ENV === "production",
httpOnly: true,
maxAge: 86400 * 1000,
sameSite: "strict",
},
})
);
レート制限
async function rateLimiter(
key: string,
maxRequests: number,
windowSeconds: number
): Promise<{ allowed: boolean; remaining: number; resetAt: number }> {
const now = Math.floor(Date.now() / 1000);
const windowKey = `ratelimit:${key}:${Math.floor(now / windowSeconds)}`;
const current = await redis.incr(windowKey);
if (current === 1) {
await redis.expire(windowKey, windowSeconds);
}
const remaining = Math.max(0, maxRequests - current);
const resetAt = (Math.floor(now / windowSeconds) + 1) * windowSeconds;
return {
allowed: current <= maxRequests,
remaining,
resetAt,
};
}
// ミドルウェアとして使用
async function rateLimitMiddleware(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
const key = req.ip || "unknown";
const result = await rateLimiter(key, 100, 60);
res.set("X-RateLimit-Remaining", String(result.remaining));
res.set("X-RateLimit-Reset", String(result.resetAt));
if (!result.allowed) {
return res.status(429).json({ error: "Too many requests" });
}
next();
}
Claude Codeでの活用
Redisキャッシュの実装をClaude Codeに依頼する例です。エッジでのキャッシュについてはエッジコンピューティング、非同期処理はジョブキュー・非同期処理も参照してください。
Redisキャッシュ層を設計して。
- Cache-Asideパターンでの読み取りキャッシュ
- 更新時のキャッシュ無効化戦略
- APIレート制限
- セッション管理
- キャッシュのヒット率モニタリング
Redisの詳細はRedis公式ドキュメントを参照してください。Claude Codeの使い方は公式ドキュメントで確認できます。
Summary
Redisキャッシュはアプリケーションのパフォーマンスを劇的に向上させます。Claude Codeを使えば、キャッシュ戦略の設計から無効化パターンの実装まで、一貫したキャッシュ層を構築できます。
Level up your Claude Code workflow
50 battle-tested prompt templates you can copy-paste into Claude Code right now.
Free PDF: Claude Code Cheatsheet in 5 Minutes
Key commands, shortcuts, and prompt examples on a single printable page.
About the Author
Masa
Engineer obsessed with Claude Code. Runs claudecode-lab.com, a 10-language tech media with 2,000+ pages.
Related Posts
Getting Started with Claude Code Agent SDK — Build Autonomous Agents Fast
Learn how to build autonomous AI agents with Claude Code Agent SDK. Covers setup, tool definitions, and multi-step execution with practical code examples.
The Complete Guide to Context Management in Claude Code
Learn practical techniques to maximize Claude Code's context window. Covers token optimization, conversation splitting, and CLAUDE.md usage.
Mastering Claude Code Hooks: Auto-Format, Auto-Test, and More
Mastering Claude Code Hooks: Auto-Format, Auto-Test, and More. A practical guide with code examples.