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.

esrun
esrun-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 flagDeno onlyDeno 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 streams are reachable through send() rather than typed methods, and its 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:

Workloadesrunnode-redisioredisBun
5 000 SET, one at a time8581029910666
20 000 SET in one batch22537420372
LRANGE over 50 000 elements15820311928
200 × HGETALL of 1 000 fields957479496205

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.

Where it is behind

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.

Last updated on
Edit this page