node-redis

repository·master·Indexed 12 days ago

https://github.com/redis/node-redis

A modern, high-performance Redis client for Node.js. Supports standard Redis commands and specialized modules including RedisJSON (@redis/json), RediSearch (@redis/search), and RedisBloom (@redis/bloom). Includes support for Microsoft Entra ID authentication via @redis/entraid.

Tokens
205.2K
Snippets
825
Records
1K
Agent score
86%

What's inside node-redis

  1. Use @redis/json for RedisJSON support

    master

    The @redis/json package provides support for the RedisJSON module, allowing you to use JSON as a native data type in Redis.

    Prerequisites:

    • You must use this package in conjunction with redis or @redis/client.
    • Your Redis server must have the RedisJSON module installed to use these commands.
  2. Use @redis/search for RediSearch support

    master

    The @redis/search package provides support for the RediSearch module, enabling indexing and querying for data stored in Redis Hashes or as JSON documents (via the RedisJSON module).

    Prerequisites:

    • Your Redis server must have the RediSearch module installed.
    • To index and query JSON documents, you must also have the RedisJSON module installed.

    This package should be used in conjunction with redis or @redis/client.

  3. Understand command batching and pipelining

    master

    Node-Redis uses setImmediate to pipeline commands.

    When performing writes, if socket.write() returns false (indicating that data is being queued in user memory because the buffer is full), the commands will continue to stack in memory until the Node.js drain event is emitted by the socket.

  4. Understand RESP type mapping to JavaScript

    master
    Node-Redis communicates with Redis using the Redis Serialization Protocol (RESP). The client automatically maps RESP types to JavaScript types. By default, the client uses the first type listed in the mapping tables below. You can customize this behavior by configuring the typeMapping option in your client configuration.
  5. Handle transaction safety with token-based authentication

    master

    Because the token manager runs in the background and may inject AUTH commands to refresh tokens, manual transaction construction is dangerous.

    Avoid manual commands: Do not use client.sendCommand(['MULTI']) and client.sendCommand(['EXEC']). An AUTH command could be injected between MULTI and EXEC, breaking the transaction.

    Recommended: Always use the official client transaction API (client.multi()).

    // Correct way to handle transactions
    const multi = client.multi();
    multi.set('key1', 'value1');
    multi.set('key2', 'value2');
    await multi.exec();
  6. Use Pub/Sub in v4

    master

    In v4, the message-like events (such as message, pmessage, etc.) have been removed. Instead of listening for events, you pass a callback function directly as the second argument to subscribe-like commands.

    • Callback: Triggered every time a message is published to the channel. It receives (message, channelName).
    • Buffer Mode: The third argument to these commands is a boolean bufferMode (defaults to false). If set to true, the callback receives a Buffer instead of a string.
    • Return Value: These commands return a Promise that fulfills upon successful execution.
    import { createClient } from 'redis';
    
    const subscriber = createClient();
    
    await subscriber.connect();
    
    // Use a callback instead of an event listener
    await subscriber.subscribe('channel_name', (message, channelName) => {
        console.info(message, channelName);
    });
  7. Understand scanIterator pool behavior and deadlocks

    master

    The scanIterator() in a Sentinel client manages master client leases efficiently. It acquires a master client lease only for the duration of each individual SCAN command and releases it before yielding the results to your loop.

    This behavior prevents deadlocks: you can safely issue other commands (e.g., sentinel.mGet(keys)) from within the for await loop body, even if your masterPoolSize is set to the default of 1.

  8. How Pub/Sub works with RESP2 and dedicated connections

    master

    When using the RESP2 protocol, a client that has active subscriptions enters a state where it can no longer execute standard commands. To use Pub/Sub alongside regular Redis commands, you must use a dedicated connection. You can create this dedicated connection by calling .duplicate() on an existing RedisClient instance.

    Note: If you are using RedisCluster or RedisSentinel, this connection management is handled automatically.

    const subscriber = client.duplicate();
    subscriber.on('error', err => console.error(err));
    await subscriber.connect();
  9. Implement optimistic locking with .watch()

    master

    You can implement optimistic locking by calling .watch(key) before starting a transaction. The transaction will abort if any of the watched keys are modified by another client or if the client reconnects between the watch and exec calls.

    Because the WATCH state is stored on the connection by the Redis server, you must use a connection pool if you need to run multiple WATCH & MULTI operations in parallel.

    // Example concept: watching a key
    await client.watch('my-key');
    const multi = client.multi();
    // ... add commands ...
    await multi.exec();
  10. When to use Connection Pooling

    master
    In most scenarios, a single Redis connection is sufficient because the node-redis client efficiently manages commands over the underlying socket. Unlike many traditional databases, Redis does not require connection pooling for optimal performance. If your specific use case requires exclusive connections, use the RedisClientPool instead of standard client configuration.