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.
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.
// 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');
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.
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 →