From 231c65e0eec2a8512b2c0c92f7561c792a86deb2 Mon Sep 17 00:00:00 2001 From: Andy Stark Date: Tue, 13 Oct 2026 11:21:29 +0100 Subject: [PATCH 1/2] DOC-7177 Document ioredis smart client handoffs (SCH) Add a "Connect using Smart client handoffs (SCH)" section to the ioredis connect page (same anchor as the other clients) and an ioredis row to the SCH support table on sch.md. Written against ioredis v6.1.0-beta.1 (redis/ioredis#2165); parked until stable v6.1.0 ships. Verified against the installed ioredis@6.1.0-beta.1 package, not the release notes: option names, defaults, and the MaintNotifications / MaintEndpointType unions come from the shipped .d.ts; the example type-checks (tsc --strict --skipLibCheck; without skipLibCheck the library's own .d.ts fails on untyped redis-errors, an upstream gap). No live handoff was tested: that needs a Redis Cloud/Software maintenance event. Scope facts from built/Redis.js and MaintenanceManager.js: - Cluster connections (ConnectionPool, subscribers, cluster/index) force maintNotifications "disabled", so the OSS Cluster API cell is "-". - Sentinel, Unix socket, custom Connector, subscriber and monitor connections still register and open the relaxed-timeout window on MIGRATING/FAILING_OVER/MOVING; only the handoff is skipped (canHandoffConnection / resolveMaintConfiguredEndpoint return false/null) and they reconnect normally. A WebFetch summary of Redis.ts claimed these were not registered at all - wrong. - RESP3 is the default since v6.0.0 (RedisOptions.js protocol: 3), so unlike node-redis the example omits a protocol option. - Error classes are exported as CommandTimeoutDuringMaintenanceError and SocketTimeoutDuringMaintenanceError (.name matches). The option JSDoc says "CommandTimeoutDuringMaintenance"; docs use the importable name. - A handoff invalidates WATCH and EXEC rejects with WatchError ("Retry it with a fresh WATCH") - not documented for node-redis. Rejected: documenting the "ioredis:maintenance" diagnostics_channel (DataHandler.js publishes each raw notification on it). No other client's SCH section documents observability hooks; add if asked. Unpark watch: re-diff built/redis/RedisOptions.d.ts, built/maintNotifications/index.d.ts and built/index.d.ts at the v6.1.0 tag; cluster support landing before GA would change the table cell and the version note. Co-Authored-By: Claude Opus 5.5 --- content/develop/clients/ioredis/connect.md | 70 ++++++++++++++++++++++ content/develop/clients/sch.md | 2 + 2 files changed, 72 insertions(+) diff --git a/content/develop/clients/ioredis/connect.md b/content/develop/clients/ioredis/connect.md index 22f3da432a..914f377d28 100644 --- a/content/develop/clients/ioredis/connect.md +++ b/content/develop/clients/ioredis/connect.md @@ -148,3 +148,73 @@ const redis = new Redis({ }, }); ``` + +## Connect using Smart client handoffs (SCH) + +*Smart client handoffs (SCH)* is a feature of Redis Cloud and +Redis Software servers that lets them actively notify clients +about planned server maintenance shortly before it happens. This +lets a client take action to avoid disruptions in service. +See [Smart client handoffs](/content/develop/clients/sch.md) +for more information about SCH. + +> [!NOTE] +> Using SCH with `ioredis` requires v6.1.0 or later. SCH is not available for +> [cluster connections](#connect-to-a-redis-cluster), so you can't use it with +> the [OSS Cluster API](/content/operate/rs/databases/configure/oss-cluster-api.md). +> [Sentinel](#connect-to-redis-sentinel), Unix socket, pub/sub subscriber, and +> monitor connections use relaxed timeouts only, and reconnect in the usual way +> instead of using pre-handoffs. + +SCH is enabled by default. Use the configuration options shown in the example +below to configure it during the connection: + +```js +const redis = new Redis({ + host: "", + port: , + maintNotifications: "auto", + maintEndpointType: "auto", + maintRelaxedCommandTimeout: 10000, + maintRelaxedSocketTimeout: 10000, + //... +}); +``` + +> [!NOTE] +> SCH requires the [RESP3](/content/develop/reference/protocol-spec.md#resp-versions) +> protocol, which is the default for `ioredis` v6.0.0 and later. SCH is disabled +> if you set `protocol: 2`. + +The available options are: + +- `maintNotifications`: (`string`) Whether or not to enable SCH. The options are + - `"disabled"`: don't use SCH + - `"enabled"`: attempt to activate SCH on the server and abort the connection if it isn't supported + - `"auto"`: attempt to activate SCH on the server and fall back to a non-SCH + connection if it isn't supported. This is the default. +- `maintEndpointType`: (`MaintEndpointType`) The type of endpoint to use for the connection. The options are: + - `"external-ip"`: use the external IP address of the server + - `"internal-ip"`: use the internal IP address of the server + - `"external-fqdn"`: use the external FQDN of the server + - `"internal-fqdn"`: use the internal FQDN of the server + - `"auto"`: auto-detect based on connection. This uses an FQDN if TLS is enabled, + and an IP address otherwise. This is the default. + - `"none"`: attempt a graceful reconnect to the current endpoint after a delay. +- `maintRelaxedCommandTimeout`: (`number`) The command timeout to use while the server is + performing maintenance. The default is 10000 (10 seconds). If a timeout happens during the maintenance period, the client receives a `CommandTimeoutDuringMaintenanceError` error. +- `maintRelaxedSocketTimeout`: (`number`) The socket timeout to use while the server is + performing maintenance. The default is 10000 (10 seconds). If a timeout happens during the maintenance period, the client receives a `SocketTimeoutDuringMaintenanceError` error. + +A pre-handoff moves the connection to a new node, which invalidates any keys +you are watching with [`WATCH`](/content/commands/watch.md). If this happens before +you execute the transaction, the client aborts it with a `WatchError` error. +Retry the transaction with a fresh `WATCH` when you receive this error. + +> [!NOTE] +> Redis Cloud supports relaxed timeouts *only* (and not pre-handoffs) for SCH if you are using +> either [AWS PrivateLink](/content/operate/rc/security/aws-privatelink.md) or +> [Google Cloud Private Service Connect](/content/operate/rc/security/private-service-connect.md) +> (see [Smart client handoffs](/content/develop/clients/sch.md#redis-cloud) for more information). +> To use relaxed timeouts with these services, you should set `maintEndpointType: "none"` +> when you connect. All other configurations have full support for both relaxed timeouts and pre-handoffs. diff --git a/content/develop/clients/sch.md b/content/develop/clients/sch.md index caef507239..c1d67af155 100644 --- a/content/develop/clients/sch.md +++ b/content/develop/clients/sch.md @@ -16,6 +16,7 @@ scope: overview relatedPages: - /develop/clients/redis-py/connect#connect-using-smart-client-handoffs-sch - /develop/clients/nodejs/connect#connect-using-smart-client-handoffs-sch +- /develop/clients/ioredis/connect#connect-using-smart-client-handoffs-sch - /develop/clients/lettuce/connect#connect-using-smart-client-handoffs-sch - /develop/clients/go/connect#connect-using-smart-client-handoffs-sch - /develop/clients/dotnet/connect#connect-using-smart-client-handoffs-sch @@ -72,6 +73,7 @@ Standard routing covers any connection that doesn't use the OSS Cluster API. | :-- | :-- | :-- | | [redis-py](/content/develop/clients/redis-py/connect.md#connect-using-smart-client-handoffs-sch) | v7.0.0 | v7.2.0 | | [node-redis](/content/develop/clients/nodejs/connect.md#connect-using-smart-client-handoffs-sch) | v5.9.0 | v5.11.0 | +| [ioredis](/content/develop/clients/ioredis/connect.md#connect-using-smart-client-handoffs-sch) | v6.1.0 | - | | [Lettuce](/content/develop/clients/lettuce/connect.md#connect-using-smart-client-handoffs-sch) | v7.0.0 | - | | [go-redis](/content/develop/clients/go/connect.md#connect-using-smart-client-handoffs-sch) | v9.16.0 | v9.18.0 | | [StackExchange.Redis](/content/develop/clients/dotnet/connect.md#connect-using-smart-client-handoffs-sch) | v3.3.0 | v3.3.0 | From 2059dc66604445bbc3f8848966a5f8a39f21a100 Mon Sep 17 00:00:00 2001 From: Andy Stark Date: Tue, 13 Oct 2026 12:56:56 +0100 Subject: [PATCH 2/2] DOC-7177 Fix ioredis connect page description, TLS example, timeout units - Frontmatter description said "Python"; now "Node.js/JavaScript", matching ioredis/_index.md. - TLS example mixed readFileSync and fs.readFileSync; all three now use bare readFileSync, matching the node-redis connect page. - SCH relaxed-timeout options state "in milliseconds" explicitly (confirmed by the RedisOptions.d.ts JSDoc). Co-Authored-By: Claude Opus 5.5 --- content/develop/clients/ioredis/connect.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/content/develop/clients/ioredis/connect.md b/content/develop/clients/ioredis/connect.md index 914f377d28..e7814a7bbb 100644 --- a/content/develop/clients/ioredis/connect.md +++ b/content/develop/clients/ioredis/connect.md @@ -9,7 +9,7 @@ categories: - oss - kubernetes - clients -description: Connect your Python application to a Redis database +description: Connect your Node.js/JavaScript application to a Redis database linkTitle: Connect title: Connect to the server weight: 20 @@ -144,7 +144,7 @@ const redis = new Redis({ tls: { key: readFileSync('./redis_user_private.key'), cert: readFileSync('./redis_user.crt'), - ca: fs.readFileSync('./redis_ca.pem'), + ca: readFileSync('./redis_ca.pem'), }, }); ``` @@ -201,9 +201,9 @@ The available options are: - `"auto"`: auto-detect based on connection. This uses an FQDN if TLS is enabled, and an IP address otherwise. This is the default. - `"none"`: attempt a graceful reconnect to the current endpoint after a delay. -- `maintRelaxedCommandTimeout`: (`number`) The command timeout to use while the server is +- `maintRelaxedCommandTimeout`: (`number`) The command timeout, in milliseconds, to use while the server is performing maintenance. The default is 10000 (10 seconds). If a timeout happens during the maintenance period, the client receives a `CommandTimeoutDuringMaintenanceError` error. -- `maintRelaxedSocketTimeout`: (`number`) The socket timeout to use while the server is +- `maintRelaxedSocketTimeout`: (`number`) The socket timeout, in milliseconds, to use while the server is performing maintenance. The default is 10000 (10 seconds). If a timeout happens during the maintenance period, the client receives a `SocketTimeoutDuringMaintenanceError` error. A pre-handoff moves the connection to a new node, which invalidates any keys