Skip to main content
Redis is the cache provider: a fast in-memory store that backs both tools.cache and (when using BullMQ) tools.queue via the same REDIS_URL.

Why

Redis gives you sub-millisecond cache reads with a minimal operational footprint. In local dev, the same memory Redis container used by BullMQ doubles as the cache store, so no extra infrastructure is needed. In production, point REDIS_URL at a managed Redis instance (e.g. Railway Redis, Upstash, or ElastiCache).

Setup

  1. In development.ts, production.ts, and test.ts, set tools.cache:
    cache: {
      client: CacheClientType.REDIS,
      url: process.env.REDIS_URL,
    }
    
  2. In compose.yml, the memory service provides Redis for both cache and queue in dev:
    memory:
      image: redis:latest
      ports:
        - 6379:6379
      healthcheck:
        test: ["CMD", "redis-cli", "ping"]
        interval: 2s
        timeout: 5s
        retries: 10
    
  3. In .env.development, set:
    REDIS_URL=redis://memory:6379
    
  4. Run make test module=backend.

Built-in helpers

The cache client ships three pre-built helpers, all accessed through tools.cache.helpers:
HelperKey prefixPurpose
webhooksEventswebhooks_eventsIdempotency check for processed Stripe webhook events
invoicePrevieworganization:invoice_previewCaches invoice preview results per organisation
globalConfigurationglobal_configurationCaches global app configuration
const cached = await tools.cache.helpers.invoicePreview.get(organizationId);
if (!cached) {
  const preview = await tools.paymentProcessor.previewInvoice(...);
  await tools.cache.helpers.invoicePreview.set(organizationId, preview);
}

Adding a new cache helper

  1. Create apps/backend/src/tools/cache/<domain>.ts. Export a build<Domain>CacheHelper(keyPrefix, logger, redisClient) factory that returns typed get/set/del methods.
  2. Register the helper in buildCacheClient inside apps/backend/src/tools/cache/index.ts:
    helpers: {
      // existing helpers...
      myDomain: buildMyDomainCacheHelper('my_domain', logger, redisClient),
    }
    
  3. Run make test module=backend.

Gotchas

  • REDIS_URL is shared between tools.cache and tools.queue (BullMQ). Changing one affects the other — keep them consistent or split intentionally.
  • Never paste a production REDIS_URL into .env.development — rotate credentials immediately if that happens.
  • Redis key collisions are possible if two helpers use overlapping prefixes. Always use distinct, namespaced prefixes.
  • The redisClient.connect() call is awaited at startup. A misconfigured or unreachable Redis URL will prevent the server from starting.

What’s next?

  • BullMQ — the queue tool that shares the same Redis instance.
  • Configuration — environment-level config.