Own Your Stack.

Own Your Stack/The Foundation/redisflex

Own your queue

redisflex

One Redis API, two modes — ioredis in production, an in-process stand-in and job queue with none.

github → MIT the foundation redis

01What it is

Most apps use Redis for three things — cache, pub/sub, and queues — and most dev and CI environments would rather not run a server for any of them. redisflex is one Redis API behind which the server is optional. In production it speaks to real Redis through ioredis; in dev, standalone, or CI it runs an in-process implementation built on a Map and an EventEmitter. Your call sites never change.

The same surface covers key/value, counters, hashes, lists, sets, sorted sets, TTL, and pub/sub, plus a sliding-window rate-limit eval in memory mode. It also ships a BullMQ-shaped in-process queue and worker, so you can drop the Redis dependency for jobs too. Flip the mode in config and your app no longer needs Redis to run — the same standalone trick as pgflex.

redisflex · two modes
// production — real Redis
const redis = createRedisAdapter({
  mode: 'ioredis',
  url: process.env.REDIS_URL!,
});

// dev / standalone — in-process
const redis = createRedisAdapter({ mode: 'memory' });

await redis.set('user:1', 'alice');
await redis.publish('events', 'user.created');
Fig. 1 — one API; the server is a config flag.

02What it does

Two modes behind one adapter

createRedisAdapter({ mode: 'ioredis' }) talks to a real server; { mode: 'memory' } runs in-process with no Redis at all. Or read the mode from the environment with createRedisAdapterFromEnv()REDISFLEX_MODE=memory for in-process, otherwise ioredis at $REDIS_URL.

The Redis surface you actually use

Key/value with EX/PX expiry, counters, hashes, lists, sets, sorted sets (including -inf/+inf and exclusive bounds), TTL, and pub/sub. Memory mode throws on unsupported set options like NX rather than silently ignoring them, so the two modes can't quietly diverge.

A BullMQ-shaped in-process queue

InMemoryQueue and InMemoryWorker match BullMQ's Queue/Worker shape — delayed jobs, attempts, exponential backoff, getJobCounts, and re-emitted completed/failed events. Run jobs without Redis, then swap to real BullMQ later by changing imports.

Sliding-window rate limits in memory mode

Memory mode recognizes the canonical sliding-window rate-limit Lua script (ZADD + ZREMRANGEBYSCORE + ZCARD + EXPIRE) passed to eval and returns the post-add count — enough for a typical rate limiter with no server in the loop.

Honest about its edges

Memory mode is single-node and not durable — it loses everything on restart, and the structures are correct but not tuned for load. Streams, geo, cluster, and MULTI/EXEC aren't covered. Use real Redis under load in production; use the stand-in everywhere a server is friction. Zero-dependency core, MIT-licensed.


03Where it sits

Part of The Foundation.

redisflex is the cache and queue layer; The Foundation is the datastores and drivers underneath, built to run with a server in production or in-process with none.

Drop the server when you don't need it.

redisflex is open source and MIT-licensed. Read the code, run it in memory mode, swap to real Redis in production.

View redisflex on GitHub →