Skip to content

Cache Overview

Xeno.JS provides a common cache API that can be backed by different cache implementations.

The cache is configured through AppBuilder and resolved through TOKENS.CACHE.

Add the cache module to your application:

import { AppBuilder } from '@xeno-js/core'
const app = new AppBuilder()
app.addCache()

The default configuration enables the in-memory cache.

You can also configure the cache explicitly:

app.addCache((options) => {
options.inMemory = true
})

For Redis configuration, see Redis Cache.

Xeno.JS currently provides:

  • In-memory cache — stores values in the current application process.
  • Redis cache — stores values in Redis and can be used when cache state must be shared outside the process.

Both implementations expose the same cache contract, so application code can resolve and use the cache without depending on the underlying storage.

After building the application, resolve TOKENS.CACHE:

import { AppBuilder, TOKENS } from '@xeno-js/core'
const app = new AppBuilder()
app.addCache()
await app.build()
const cache = app.resolve(TOKENS.CACHE)

The resolved value is the configured cache implementation.

await cache.set('user:123', { id: '123', name: 'Alice' }, 60)
const user = await cache.get<{ id: string; name: string }>('user:123')

The third argument of set() is the TTL in seconds.

const exists = await cache.has('user:123')
await cache.remove('user:123')
const created = await cache.setIfAbsent(
'lock:123',
{ locked: true },
30,
)

The method returns true when the value is stored and false when the key already exists.

await cache.clear()

The configured cache also exposes the atomic increment() operation:

const count = await cache.increment('counter', 60)

If the key does not exist, the counter starts from 1.

The configured cache is used by Xeno.JS itself for several application features.

The query pipeline can cache query results when caching is configured on a query.

For example, a query can provide:

cacheOptions: {
cacheKey: 'users:list',
ttl: 60,
bypassCache: false,
consistentRead: false,
isUserScoped: false,
}

The query caching pipeline uses TOKENS.CACHE to read and store the result.

For details about query caching, see the CQRS documentation.

Command idempotency uses the same cache abstraction to store locks and previously processed command results.

This means changing the configured cache implementation does not require changing the idempotency feature.

HTTP rate limiting also uses the configured cache.

This allows rate-limit state to be stored through the same cache abstraction used by the rest of the application.

When you call addPipeline(), Xeno.JS automatically queues the cache module if it has not already been configured.

The same happens when you enable middlewares with addMiddlewares().

Therefore, you normally only need to call addCache() explicitly when you want to configure the cache yourself, for example to select Redis.

Use the in-memory cache when:

  • the cache only needs to live inside one application process;
  • you are developing locally;
  • shared cache state is not required.

Use Redis when:

  • multiple application instances need to share cached values;
  • cache state must live outside the application process;
  • you need a distributed cache.

For Redis configuration, see Redis Cache.


Xeno.JS is an MIT-licensed open source project. It can grow thanks to the support of these awesome people. If you’d like to join them, please read more at support section