Guides

Guide - Redis Caching

Redis setup, cache key patterns, and common CLI commands used in booki-api.

booki-api uses Redis to cache frequently-read data (organizations, packages, branches, users) and reduce MongoDB round-trips. This guide covers installation, configuration, cache key patterns, and day-to-day CLI commands.


Setup

  1. Sign up at redis.com/try-free — free 30 MB tier is enough for development.
  2. Create a database.
  3. Copy host, port, and password into .env:
REDIS_HOST=redis-12345.c1.us-east-1-2.ec2.cloud.redislabs.com
REDIS_PORT=12345
REDIS_PASSWORD=your-password
REDIS_TLS=true

Option B — Upstash (serverless, pay-per-request)

  1. Sign up at upstash.com.
  2. Create a Redis database.
  3. Copy the REST endpoint credentials — Upstash requires TLS:
REDIS_HOST=us1-your-db.upstash.io
REDIS_PORT=6379
REDIS_PASSWORD=your-password
REDIS_TLS=true

Option C — Local Redis

# macOS
brew install redis && brew services start redis

# Linux
sudo apt-get install redis-server && sudo systemctl start redis

# Windows — download from https://github.com/microsoftarchive/redis/releases
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=
REDIS_TLS=false

Environment Variables

VariableRequiredDefaultDescription
REDIS_HOSTYesRedis server hostname
REDIS_PORTYesRedis server port
REDIS_PASSWORDCloud onlyAuth password (leave empty for local)
REDIS_TLSCloud onlyfalseSet true for Redis Cloud / Upstash

How Caching Works in booki-api

The caching layer sits in repositories. Each repo method optionally passes a cacheOptions object to the base repository:

// Cache for 10 minutes with a descriptive key
const cacheOptions = { ttl: 600, key: `org:${id}` };
const org = await base.getById(
  id,
  pipeline,
  true,
  cacheOptions,
  "organization",
);

On cache hit, MongoDB is bypassed entirely. On cache miss, the query runs and the result is stored.

Cache is invalidated by the service layer on write operations (create / update / delete):

await cache.del(`org:${id}`);

Cache Key Patterns

Key PatternWhat It CachesTTL
org:{organizationId}Organization document10 min
branch:{branchId}Branch document10 min
branch:slug:{slug}:{organizationId}Branch by slug scoped to org10 min
package:{packageId}Service package10 min
packages:org:{organizationId}All packages for an org10 min
user:{userId}User profile10 min
tenant:slug:{slug}Org ID resolved from slug5 min

Keys are always scoped by organizationId where applicable to prevent cross-tenant cache collisions.


Common CLI Commands

Connect to your Redis instance:

# Local
redis-cli

# Redis Cloud / remote (with TLS)
redis-cli -h YOUR_HOST -p YOUR_PORT -a YOUR_PASSWORD --tls

Inspect keys

# List all booki-api keys
KEYS org:*
KEYS branch:*
KEYS user:*

# Scan (safer on large datasets — non-blocking)
SCAN 0 MATCH org:* COUNT 100

Read and delete

# Read a value
GET org:507f191e810c19729de860ea

# Check TTL (seconds remaining)
TTL org:507f191e810c19729de860ea

# Delete a single key
DEL org:507f191e810c19729de860ea

# Delete all keys matching a pattern (use with caution)
# Redis < 7: no UNLINK with pattern; use a pipeline
redis-cli --scan --pattern "org:*" | xargs redis-cli DEL

Flush (development only)

# Clear ALL keys in current database — destructive, dev only
FLUSHDB

# Clear all databases — never use in production
FLUSHALL

Server info

INFO memory        # Memory usage
INFO stats         # Hit/miss statistics
INFO keyspace      # Key count per database

Troubleshooting

SymptomLikely CauseFix
ECONNREFUSED on startupRedis not runningStart Redis; check host/port in .env
WRONGPASS errorIncorrect REDIS_PASSWORDDouble-check password in Redis dashboard
TLS handshake errorsMissing REDIS_TLS=trueSet REDIS_TLS=true for cloud instances
Stale data after updateCache not invalidatedVerify service layer calls cache.del(key) after writes
High memory usageTTLs too long or no expiry setReview and lower TTL values; add EXPIRE if missing

Verify Connection

redis-cli -h $REDIS_HOST -p $REDIS_PORT -a $REDIS_PASSWORD ping
# Expected: PONG