Redis Caching Strategies: Optimizing Application Performance
May 5, 2024•2 min read
RedisCachingPerformanceBackend
# Redis Caching Strategies: Optimizing Application Performance
Redis is an in-memory data structure store that serves as a cache, message broker, and database. Effective Redis usage can dramatically improve application performance.
## Caching Patterns
### Cache-Aside Pattern
Application checks cache first, then database:
```typescript
async function getUser(id: string): Promise<User> {
// Check cache
const cached = await redis.get(`user:${id}`);
if (cached) return JSON.parse(cached);
// Fetch from database
const user = await db.user.findUnique({ where: { id } });
// Store in cache
await redis.setex(`user:${id}`, 3600, JSON.stringify(user));
return user;
}
```
### Write-Through Pattern
Write to cache and database simultaneously:
```typescript
async function updateUser(id: string, data: UpdateUserDto): Promise<User> {
const user = await db.user.update({ where: { id }, data });
await redis.setex(`user:${id}`, 3600, JSON.stringify(user));
return user;
}
```
### Cache Invalidation
Strategies for keeping cache fresh:
```typescript
// Time-based expiration
await redis.setex('key', 3600, 'value');
// Event-based invalidation
async function deleteUser(id: string) {
await db.user.delete({ where: { id } });
await redis.del(`user:${id}`);
await redis.del('users:list'); // Invalidate related cache
}
```
## Advanced Patterns
### Distributed Locking
Prevent race conditions:
```typescript
async function acquireLock(key: string, ttl: number): Promise<boolean> {
const result = await redis.set(key, 'locked', 'EX', ttl, 'NX');
return result === 'OK';
}
async function processOrder(orderId: string) {
const lockKey = `lock:order:${orderId}`;
const acquired = await acquireLock(lockKey, 30);
if (!acquired) {
throw new Error('Order is being processed');
}
try {
// Process order
} finally {
await redis.del(lockKey);
}
}
```
### Rate Limiting
Implement rate limiting with Redis:
```typescript
async function rateLimit(userId: string, limit: number, window: number): Promise<boolean> {
const key = `rate:${userId}`;
const current = await redis.incr(key);
if (current === 1) {
await redis.expire(key, window);
}
return current <= limit;
}
```
## Conclusion
Redis is powerful for caching, but requires careful strategy. Choose patterns that match your use case and implement proper invalidation to maintain data consistency.