Node.js Redis cheatsheet.
Choose
- ioredis: feature-rich, cluster-aware.
- node-redis: official, modern API.
ioredis
npm i ioredis
import Redis from "ioredis";
const r = new Redis("redis://localhost:6379");
await r.set("k", "v");
const v = await r.get("k");
await r.quit();
Pool / cluster (ioredis)
import Redis, { Cluster } from "ioredis";
const cluster = new Cluster([
{ host: "node1", port: 7000 },
{ host: "node2", port: 7000 },
]);
node-redis (v4+)
npm i redis
import { createClient } from "redis";
const r = await createClient({ url: "redis://localhost:6379" })
.on("error", (e) => console.error(e))
.connect();
await r.set("k", "v");
const v = await r.get("k");
await r.quit();
Pipeline
// ioredis
const p = r.pipeline();
p.set("a", 1);
p.set("b", 2);
const results = await p.exec();
// node-redis
const multi = r.multi();
multi.set("a", 1);
multi.set("b", 2);
const results = await multi.exec();
Transactions
// ioredis
const result = await r.multi()
.set("a", 1)
.incr("counter")
.exec();
Pub/sub
// ioredis
const sub = new Redis();
sub.subscribe("channel");
sub.on("message", (channel, msg) => {
console.log(msg);
});
// Publish on different client (subscribed cannot publish)
const pub = new Redis();
await pub.publish("channel", "hi");
Streams
// Add
await r.xadd("events", "*", "type", "click", "url", "/");
// Read
const res = await r.xread("BLOCK", 5000, "STREAMS", "events", "$");
Hashes
await r.hset("user:1", { name: "Alice", age: 30 });
const all = await r.hgetall("user:1");
await r.hget("user:1", "name");
Set / get JSON
const set = (k: string, v: unknown, ttl?: number) =>
ttl ? r.setex(k, ttl, JSON.stringify(v)) : r.set(k, JSON.stringify(v));
const get = async <T>(k: string): Promise<T | null> => {
const raw = await r.get(k);
return raw ? JSON.parse(raw) : null;
};
TTL
await r.set("k", "v", "EX", 60); // ioredis style
await r.setex("k", 60, "v");
await r.expire("k", 60);
const ttl = await r.ttl("k");
SCAN
const stream = r.scanStream({ match: "user:*", count: 100 });
stream.on("data", (keys) => {
for (const k of keys) console.log(k);
});
stream.on("end", () => {});
Lua
const script = `return redis.call('GET', KEYS[1])`;
const val = await r.eval(script, 1, "mykey");
// Cache
r.defineCommand("myCmd", { numberOfKeys: 1, lua: script });
const val2 = await r.myCmd("mykey");
Error handling
r.on("error", (err) => console.error("Redis error:", err));
r.on("connect", () => console.log("connected"));
r.on("ready", () => console.log("ready"));
r.on("close", () => console.log("close"));
r.on("reconnecting", () => console.log("reconnecting"));
Express + Redis session
npm i express-session connect-redis ioredis
import session from "express-session";
import RedisStore from "connect-redis";
app.use(session({
store: new RedisStore({ client: redis }),
secret: "...",
resave: false,
saveUninitialized: false,
cookie: { httpOnly: true, secure: true, sameSite: "lax", maxAge: 86400 * 7 * 1000 },
}));
BullMQ (queue lib)
npm i bullmq
import { Queue, Worker } from "bullmq";
const queue = new Queue("emails", { connection: r });
await queue.add("send", { to: "[email protected]" });
const worker = new Worker("emails", async (job) => {
await sendEmail(job.data);
}, { connection: r });
Robust job queue on Redis.
Common mistakes
- Single client used for pub/sub + commands (won’t work; subscribed clients can’t run other commands).
- Not handling reconnects.
- Forgetting
await. r.set(k, JSON)without stringify.- Mixing ioredis + node-redis API.
Read this next
If you want my BullMQ setup, it’s at rajpoot.dev .
Building something AI-, backend-, or data-heavy and want a second pair of eyes? I do consulting and freelance work — see my projects and ways to reach me at rajpoot.dev .