1
0
mirror of https://github.com/redis/node-redis.git synced 2025-07-31 05:44:24 +03:00
Files
node-redis/docs/v5.md
Nikolay Karadzhov 62ac8b7c32 fix(client): make unstable cmds throw (#2990)
As per the docs, unstableResp3 commands should throw
when client is created with { RESP: 3, unstableResp3: false|undefined }

fixes #2989
2025-06-06 15:38:52 +03:00

5.1 KiB

RESP3 Support

Node Redis v5 adds support for RESP3, the new Redis serialization protocol. RESP3 offers richer data types and improved type handling compared to RESP2.

To use RESP3, specify it when creating your client:

import { createClient } from 'redis';

const client = createClient({
  RESP: 3
});

Type Mapping

With RESP3, you can leverage the protocol's richer type system. You can customize how different Redis types are represented in JavaScript using type mapping:

import { createClient, RESP_TYPES } from 'redis';

// By default
await client.hGetAll('key'); // Record<string, string>

// Use Map instead of plain object
await client.withTypeMapping({
  [RESP_TYPES.MAP]: Map
}).hGetAll('key'); // Map<string, string>

// Use both Map and Buffer
await client.withTypeMapping({
  [RESP_TYPES.MAP]: Map,
  [RESP_TYPES.BLOB_STRING]: Buffer
}).hGetAll('key'); // Map<string, Buffer>

This replaces the previous approach of using commandOptions({ returnBuffers: true }) in v4.

PubSub in RESP3

RESP3 uses a different mechanism for handling Pub/Sub messages. Instead of modifying the onReply handler as in RESP2, RESP3 provides a dedicated onPush handler. When using RESP3, the client automatically uses this more efficient push notification system.

Known Limitations

Unstable Commands

Some Redis commands have unstable RESP3 transformations. These commands will throw an error when used with RESP3 unless you explicitly opt in to using them by setting unstableResp3: true in your client configuration:

const client = createClient({
  RESP: 3,
  unstableResp3: true
});

The following commands have unstable RESP3 implementations:

  1. Stream Commands:

    • XREAD and XREADGROUP - The response format differs between RESP2 and RESP3
  2. Search Commands (RediSearch):

    • FT.AGGREGATE
    • FT.AGGREGATE_WITHCURSOR
    • FT.CURSOR_READ
    • FT.INFO
    • FT.PROFILE_AGGREGATE
    • FT.PROFILE_SEARCH
    • FT.SEARCH
    • FT.SEARCH_NOCONTENT
    • FT.SPELLCHECK
  3. Time Series Commands:

    • TS.INFO
    • TS.INFO_DEBUG

If you need to use these commands with RESP3, be aware that the response format might change in future versions.

Sentinel Support

Sentinel

multi.exec<'typed'> / multi.execTyped

We have introduced the ability to perform a "typed" MULTI/EXEC transaction. Rather than returning Array<ReplyUnion>, a transaction invoked with .exec<'typed'> will return types appropriate to the commands in the transaction where possible:

const multi = client.multi().ping();
await multi.exec(); // Array<ReplyUnion>
await multi.exec<'typed'>(); // [string]
await multi.execTyped(); // [string]

Client Side Caching

Node Redis v5 adds support for Client Side Caching, which enables clients to cache query results locally. The server will notify the client when cached results are no longer valid.

Client Side Caching is only supported with RESP3.

Usage

There are two ways to implement client side caching:

Anonymous Cache

const client = createClient({
  RESP: 3,
  clientSideCache: {
    ttl: 0,             // Time-to-live in milliseconds (0 = no expiration)
    maxEntries: 0,      // Maximum entries to store (0 = unlimited)
    evictPolicy: "LRU"  // Eviction policy: "LRU" or "FIFO"
  }
});

In this instance, the cache is managed internally by the client.

Controllable Cache

import { BasicClientSideCache } from 'redis';

const cache = new BasicClientSideCache({
  ttl: 0,
  maxEntries: 0,
  evictPolicy: "LRU"
});

const client = createClient({
  RESP: 3,
  clientSideCache: cache
});

With this approach, you have direct access to the cache object for more control:

// Manually invalidate keys
cache.invalidate(key);

// Clear the entire cache
cache.clear();

// Get cache metrics
// `cache.stats()` returns a `CacheStats` object with comprehensive statistics.
const statistics = cache.stats();

// Key metrics:
const hits = statistics.hitCount;        // Number of cache hits
const misses = statistics.missCount;      // Number of cache misses
const hitRate = statistics.hitRate();     // Cache hit rate (0.0 to 1.0)

// Many other metrics are available on the `statistics` object, e.g.:
// statistics.missRate(), statistics.loadSuccessCount,
// statistics.averageLoadPenalty(), statistics.requestCount()

Pooled Caching

Client side caching also works with client pools. For pooled clients, the cache is shared across all clients in the pool:

const client = createClientPool({RESP: 3}, {
  clientSideCache: {
    ttl: 0,
    maxEntries: 0,
    evictPolicy: "LRU"
  },
  minimum: 5
});

For a controllable pooled cache:

import { BasicPooledClientSideCache } from 'redis';

const cache = new BasicPooledClientSideCache({
  ttl: 0,
  maxEntries: 0,
  evictPolicy: "LRU"
});

const client = createClientPool({RESP: 3}, {
  clientSideCache: cache,
  minimum: 5
});