Skip to content

Stores

Stores are the backing implementations used to read, write, and delete cached values. You can use a single store or layer several stores in priority order.

createTTLStore() creates an in-memory store backed by @isaacs/ttlcache.

import { createTTLStore, Time } from '@alexmchan/memocache'
const store = createTTLStore({
defaultTTL: 5 * Time.Minute,
})

Use it for low-latency local memory caching. It is process-local and not shared across instances.

Treat cached values as immutable. For speed, the memory store returns the stored reference rather than a copy (serialized tiers like Redis return fresh copies). Mutating a value you read back would corrupt the shared entry — so in development returned values are deep-frozen and mutation throws loudly. If you need to mutate results, enable cloning:

const store = createTTLStore({ defaultTTL: 5 * Time.Minute, cloneOnGet: true })

cloneOnGet returns a structuredClone of the value on every get (a small cost; off by default).

Backed by Node.js’s standard-library node:sqlite module — no external dependencies, no native bindings to compile. Requires Node.js >= 24 (the module ships in 24 with an experimental warning and is stabilized in 26).

Install:

Terminal window
pnpm install @alexmchan/memocache-store-sqlite
import { createCache } from '@alexmchan/memocache'
import { Time } from '@alexmchan/memocache'
import { createSqliteStore } from '@alexmchan/memocache-store-sqlite'
const sqliteStore = createSqliteStore({
location: './cache.db', // or ':memory:' (default)
cleanupInterval: 5 * Time.Minute,
defaultTTL: 10 * Time.Minute,
})
const cache = createCache({
stores: [sqliteStore],
defaultFresh: 1 * Time.Minute,
})

Options:

  • database — an existing node:sqlite DatabaseSync instance (caller-owned; not closed on dispose)
  • location — path used to open a database when database is omitted; defaults to ':memory:'
  • tableName
  • defaultTTL
  • cleanupInterval
  • logger

For local and file-backed SQLite this is the store to reach for. For a remote SQLite database, put a network store (such as Redis) in front of your remote data instead — memocache no longer ships a Turso/libsql:// store.

Install:

Terminal window
pnpm install @alexmchan/memocache-store-redis ioredis
import { createRedisStore } from '@alexmchan/memocache-store-redis'
import { Redis } from 'ioredis'
import { Time } from '@alexmchan/memocache'
const redisStore = createRedisStore({
redisClient: new Redis({
host: 'localhost',
port: 6379,
}),
defaultTTL: 5 * Time.Minute,
})

This store uses ioredis, so it is intended for Node runtimes rather than edge runtimes.

If you omit redisClient, the store constructs new Redis() (ioredis’s default of localhost:6379) and logs a warning — pass an explicit client in production to avoid a silent misconnection.

import { createUpstashRedisStore } from '@alexmchan/memocache-store-redis'
import { Redis } from '@upstash/redis'
import { Time } from '@alexmchan/memocache'
const redisRestStore = createUpstashRedisStore({
redisClient: new Redis({
url: process.env.UPSTASH_REDIS_REST_URL,
token: process.env.UPSTASH_REDIS_REST_TOKEN,
}),
defaultTTL: 5 * Time.Minute,
})

If you omit redisClient, the store reads UPSTASH_REDIS_REST_URL and UPSTASH_REDIS_REST_TOKEN from the environment.

When multiple stores are configured:

  • reads check stores from first to last
  • writes update every store
  • fresh hits from lower-priority stores are promoted back into earlier stores

A common layout is:

createCache({
stores: [memoryStore, redisStore],
})

That gives you fast in-process hits with a persistent fallback behind it.