Jobs & Cache · infrastructure/cache

Production-ready adapter

Redis,
optional but ready.

Redis is the shared substrate for three subsystems here — caching, background jobs and rate limiting. It is optional in dev: the cache falls back to an in-memory store, so a fresh clone runs with nothing external, and scales out the moment you set REDIS_URL.

Graceful fallback by design

The cache factory returns a Redis-backed store when REDIS_URL is present and an in-memory LRU otherwise. Single-instance dev and prod work with no Redis; multi-instance deployments set REDIS_URL and get a distributed cache with no code change.

factory.ts
 1  export const createCacheStore = ({ redisUrl, logger }) => {
 2    if (!redisUrl) {
 3      return new InMemoryCacheStore();
 4    }
 5    const redis = new Redis(redisUrl, { lazyConnect: true });
 6    return new RedisCacheStore(redis);
 7  };

Three subsystems, one dependency

Cache

Redis store when REDIS_URL is set, in-memory LRU otherwise — safe for single-instance, required for multi-instance.

Jobs

BullMQ workers and queues connect through a dedicated ioredis connection with the null-retry quirk handled.

Rate limiting

Each limiter tier (read / write / auth-ip / auth-email) has its own Redis store with a unique key prefix so counters never collide.

Boots with nothing

Optional adapters no-op or fall back when unset — the boilerplate always starts on the minimum required env.

Configuration reference

Environment variables

  • REDIS_URLoptional

    unset → in-memory cache; required for jobs & distributed cache

  • JOBS_REDIS_URLoptional

    optional dedicated Redis for BullMQ

Where it lives

  • apps/server/src/infrastructure/cache/factory.ts
  • apps/server/src/infrastructure/jobs/redis-connection.ts

Cache and queues that scale when you do.

Run with nothing external in dev; set one URL to go distributed in prod.