Redis compatibility and limits
How it compares
Every cell was produced by running the client, not by reading its documentation. Node and Deno have no built-in Redis, so both npm clients are shown: redis (node-redis, the official one) and ioredis (about twice the downloads, same organisation). They differ enough that showing only one would misreport Node.
Produced by bench/db/redis/features.mjs against Redis 8.10.2 with node-redis 6.2.1, ioredis 6.0.0, Bun 1.4.2 and esrun 0.32.0 (2026-09-26); the cluster, Sentinel and private-CA rows are checked as available APIs, since one server cannot exercise them.
esrunesrun-redis | Node/Deno node-redis 6 | Node/Deno ioredis 6 | Bun built-in | |
|---|---|---|---|---|
| Ships with the runtime | ||||
| RESP3 negotiated by default | ||||
| Exact 64-bit integers | ||||
| Binary-safe values | ||||
| Pub/sub | ||||
| Pipeline builder | ||||
MULTI/EXEC API | ||||
WATCH | ||||
| Cluster | ||||
| Sentinel | ||||
| Streams & consumer groups | ||||
| TLS with a private CA | ||||
| Auto-reconnect | ||||
| Unbounded-block guard | ||||
| Portable error codes | ||||
| Scoped by a capability flag | Deno only | Deno only |
Exact 64-bit integers is the only row that changes an answer. INCRBY k 9007199254740993 returns 9007199254740993n here and 9007199254740992 — a number, off by one — on all three others.
The partial cells. node-redis and Bun have no pipeline builder; both pipeline commands issued together, so Promise.all is the idiom rather than a missing feature. Bun's client has no multi, watch, cluster or Sentinel at all. esrun's reconnect is partial because it is off by default — a deliberate disagreement rather than a gap: turning it on changes what a thrown error means, and a pool already replaces dead connections.
Speed
Wall ms, min of 5, from Benchmarks:
| Workload | esrun | node-redis | ioredis | Bun |
|---|---|---|---|---|
5 000 SET, one at a time | 858 | 1029 | 910 | 666 |
20 000 SET in one batch | 225 | 374 | 203 | 72 |
LRANGE over 50 000 elements | 158 | 203 | 119 | 28 |
200 × HGETALL of 1 000 fields | 957 | 479 | 496 | 205 |
Bun's client is native C++ and leads everything. Among the JavaScript clients, esrun is fastest where the round trip dominates — and does it in about a third of the memory (38 MB against 79–124) — and ahead of the official node-redis on batches and list scans.
Repeated HGETALL is twice as slow as both npm clients. That is not decoding in general — the list scan is mid-pack — but the map path specifically: a RESP3 map becomes a pair array of wrapper objects, each holding a copied Uint8Array, before anything becomes a key or a value. ioredis negotiates RESP3 too and builds the same object twice as fast, so it is an implementation cost rather than a protocol one, and it is fixable.
Not supported
Named rather than left to be discovered: reading from replicas in a cluster, cluster-aware pub/sub, RESP3 client-side caching (server attributes are read and discarded), MONITOR, and cancelling a command in flight — Redis has no such thing, which is why { signal } rejects the caller when the reply arrives rather than stopping the work.