원클릭으로
caching-strategies
When improving read performance and reducing database load.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
When improving read performance and reducing database load.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
When designing loosely coupled systems that react to state changes asynchronously.
When setting up telemetry, debugging distributed systems, or standardizing application output.
When creating or extending an HTTP API for client consumption.
When addressing slow application endpoints, high database CPU usage, or standardizing data access patterns.
When designing how a system recovers from and reports failures.
When asynchronously reviewing peer code before merging into the main branch.
| name | caching-strategies |
| description | When improving read performance and reducing database load. |
| version | 2.0.0 |
| category | architecture |
| tags | ["architecture","performance","caching"] |
| skill_type | architecture |
| author | skiLLM |
| license | MIT |
| compatible_agents | ["claude-code","cursor","copilot","codex"] |
| estimated_context_tokens | 1800 |
| dangerous | false |
| requires_review | false |
| security_level | safe |
| dependencies | ["database-query-optimization"] |
| triggers | ["performance","latency","database load","cache","redis"] |
| permissions | {"filesystem":{"read":true,"write":true},"network":{"outbound":true},"shell":{"execute":true}} |
| input_requirements | ["slow read endpoints","cache infrastructure"] |
| output_contract | ["cache never source of truth","always has fallback","ttl enforced"] |
| failure_conditions | ["cache becomes source of truth","no fallback logic","infinite ttl"] |
| last_updated | "2026-05-15T00:00:00.000Z" |
Databases are slow; caches are fast. This skill teaches teams to strategically cache frequently accessed data in fast storage (Redis, Memcached) to intercept requests before they hit the database, dramatically reducing latency and database load. Caching is NOT a substitute for proper database optimization.
❌ Anti-pattern (No fallback, infinite TTL, no invalidation):
// WRONG: No fallback if cache fails
const getUser = async (userId) => {
return redis.get(`user:${userId}`); // Fails if Redis is down
};
// WRONG: Infinite TTL
redis.set(`config:app-settings`, settings); // Never expires = stale data forever
// WRONG: No invalidation on update
async function updateUser(userId, data) {
await db.users.update(userId, data);
// Forgot to clear cache - stale data served
}
// WRONG: Cache stampede - all requests hit DB when key expires
const getExpensiveData = async () => {
const cached = await redis.get('expensive-data');
if (!cached) {
// All concurrent requests hit this - DB spike
const data = await slowQuery();
await redis.set('expensive-data', data, { ex: 3600 });
return data;
}
return cached;
};
✅ Correct pattern (Fallback, TTL, invalidation, stampede prevention):
// CORRECT: Fallback to database on cache miss or failure
const getUser = async (userId) => {
try {
const cached = await redis.get(`user:${userId}`);
if (cached) return JSON.parse(cached);
} catch (e) {
logger.warn('Cache miss, falling back to DB', e);
}
// Fallback to DB
const user = await db.users.findById(userId);
// Repopulate cache
try {
await redis.setex(`user:${userId}`, 3600, JSON.stringify(user)); // 1 hour TTL
} catch (e) {
logger.warn('Failed to cache, but returning DB data', e);
}
return user;
};
// CORRECT: TTL on all cache entries
redis.setex('config:app-settings', 86400, JSON.stringify(settings)); // 24 hour TTL
// CORRECT: Invalidate cache on mutations
async function updateUser(userId, data) {
await db.users.update(userId, data);
await redis.del(`user:${userId}`); // Clear specific key
}
// CORRECT: Prevent cache stampede with locks
const stampedeLock = new Mutex();
const getExpensiveData = async () => {
const cached = await redis.get('expensive-data');
if (cached) return JSON.parse(cached);
// Use lock to ensure only one request fetches from DB
return stampedeLock.runExclusive(async () => {
// Double-check if another request already populated cache
const cached = await redis.get('expensive-data');
if (cached) return JSON.parse(cached);
const data = await slowQuery();
await redis.setex('expensive-data', 3600, JSON.stringify(data));
return data;
});
};