โšก

Redis & Cache

๐Ÿ‘จโ€๐Ÿณ Chef

Cache and in-memory data

Redis stores data in RAM for ultra-fast access.


Use cases

UseWhy Redis
CacheAvoid slow queries
SessionsUser state
Rate limitingCount requests
QueuesBackground jobs

Installation

# macOS
brew install redis
brew services start redis

# Docker
docker run -d --name redis -p 6379:6379 redis:7

Basic commands

redis-cli

# Strings
SET user:1 "Ana"
GET user:1
SETEX token:abc 3600 "data"  # Expires in 1 hour

# Counters
INCR page:views
INCRBY api:calls 10

# Hashes
HSET user:1 name "Ana" email "ana@email.com"
HGETALL user:1

With Node.js

import { Redis } from 'ioredis'

const redis = new Redis()

// Cache
async function getUser(id: string) {
  const cached = await redis.get(`user:${id}`)
  if (cached) return JSON.parse(cached)

  const user = await db.users.findUnique({ where: { id } })
  await redis.setex(`user:${id}`, 3600, JSON.stringify(user))
  return user
}

๐Ÿฆ Fintech Case: Rate Limiting for APIs

Financial APIs are targets for brute force attacks and abuse. Redis is perfect for implementing robust rate limiting:

import { Redis } from 'ioredis'

const redis = new Redis()

// Sliding window rate limiter
async function checkRateLimit(userId: string, action: string): Promise<boolean> {
  const key = `ratelimit:${action}:${userId}`
  const now = Date.now()
  const windowMs = 60000 // 1 minute

  // Limits per action (stricter for sensitive operations)
  const limits: Record<string, number> = {
    'transfer': 5,      // 5 transfers/min
    'login': 10,        // 10 attempts/min
    'api_call': 100,    // 100 calls/min
    'otp_request': 3,   // 3 OTP codes/min
  }

  const limit = limits[action] || 60

  // Sliding window with sorted sets
  await redis.zremrangebyscore(key, 0, now - windowMs)
  const count = await redis.zcard(key)

  if (count >= limit) {
    // Log blocked attempt for security analysis
    await redis.lpush('security:blocked_requests', JSON.stringify({
      userId, action, timestamp: now, count
    }))
    return false // Blocked
  }

  await redis.zadd(key, now, `${now}`)
  await redis.expire(key, 60)
  return true // Allowed
}

// Middleware for Express/Fastify
async function rateLimitMiddleware(req, res, next) {
  const userId = req.user?.id || req.ip
  const allowed = await checkRateLimit(userId, 'api_call')

  if (!allowed) {
    // Standard rate limiting headers
    res.set('Retry-After', '60')
    res.set('X-RateLimit-Limit', '100')
    res.set('X-RateLimit-Remaining', '0')
    return res.status(429).json({ error: 'Too many requests' })
  }

  next()
}

Strategies by operation

OperationLimitWindowAction when exceeded
Failed login515 minTemp block + alert
Transfer101 hourRequire additional MFA
Balance check1001 minRate limit only
OTP request35 minBlock + notification

๐Ÿ’ก Rate limiting with Redis protects against brute force and credential stuffing attacks, meeting PCI DSS security requirements.


Practice

โ†’ Cache with Redis