---
title: "@unikvs/valkey"
description: "How to use @unikvs/valkey, which stores byte sequences in Valkey from Node.js."
---

## Overview [#overview]

`@unikvs/valkey` is a storage plugin that stores byte sequences in Valkey. Node.js only Use it for caches or temporary data shared across nodes.

- `name` is `"Valkey"`, and `isOpen` reports whether it is open.
- `open()` connects, and `close()` disconnects when done.
- This storage prefixes keys with `"unikvs:"` by default, limiting the scope of `clear()` deletions.
- When the connection URL is omitted, the `VALKEY_URL` (or `REDIS_URL`) environment variable is used.
- When `ttl` is specified, written keys get an expiration (in milliseconds).

Install it with the following command:

```package-install
npm install @unikvs/valkey
```

A Valkey server is required separately.

## Usage [#usage]

Valkey implements IStorage. Pass it to UniKvs via persist().

```ts
import { Valkey } from "@unikvs/valkey";
```

### Valkey [#valkey]

Storage that saves to Valkey. Callers open it with `open()` and close it with `close()` when done.

The constructor arguments are as follows:

| Prop | Type | Default | Description |
| - | - | - | - |
| `url?` | `[#valkey-url] string \| undefined` | - | The connection URL (`valkey://` / `redis://` / `rediss://` form). Resolved from environment variables when omitted. |
| `options?` | `[#valkey-options] ValkeyStorageOptions` | - | Options configuring the client and this package's behavior. |

### ValkeyStorageOptions [#valkeystorageoptions]

`ioredis` `RedisOptions` plus this package's own fields. `ioredis` fields are passed through as-is.

| Prop | Type | Default | Description |
| - | - | - | - |
| `keyPrefix?` | `[#valkeystorageoptions-keyprefix] string` | - | The prefix prepended to every key. Defaults to `"unikvs:"`. |
| `cluster?` | `[#valkeystorageoptions-cluster] ValkeyClusterSpec` | - | The cluster endpoints. Unsupported in v1, so specifying it is an error. |
| `closeTimeout?` | `[#valkeystorageoptions-closetimeout] number` | - | The wait time (in milliseconds) for disconnection in `close()`. Defaults to `5000`. |
| `client?` | `[#valkeystorageoptions-client] ValkeyClient` | - | The client used by the storage. When specified, no connection or disconnection is performed and the caller owns it. |
| `ttl?` | `[#valkeystorageoptions-ttl] number` | - | The expiration (in milliseconds) attached to written keys. Keys never expire when omitted. |

### ValkeyClusterSpec [#valkeyclusterspec]

The type specifying cluster endpoints. Unsupported in v1, so specifying it is an error.

| Prop | Type | Default | Description |
| - | - | - | - |
| `nodes` | `[#valkeyclusterspec-nodes] readonly ClusterNode[]` | - | The cluster nodes to connect to. |
| `options?` | `[#valkeyclusterspec-options] ClusterOptions` | - | Options passed to the `ioredis` `Cluster`. |

### ValkeyClient [#valkeyclient]

The minimal client shape used to communicate with Valkey. Since Valkey is compatible with the Redis protocol, the `ioredis` `Redis` client can be used as-is. In tests, a fake satisfying this shape can be passed via the `client` option.

The following example saves a value and reads it back:

```ts
import { Valkey } from "@unikvs/valkey";
import * as unikvs from "unikvs";

const kvs = new unikvs.Builder<{ file: unikvs.Value<Uint8Array> }>()
  .persist(new Valkey("redis://127.0.0.1:6379"))
  .build();

await kvs.open();

await kvs.set("file", new Uint8Array([0, 1, 2]));

const data = await kvs.get("file");
console.log(data); // Uint8Array(3) [0, 1, 2]

await kvs.close();
```

## Data types [#data-types]

| Operation                            | Data type                 |
| ------------------------------------ | ------------------------- |
| `write` / `read`                     | `Uint8Array<ArrayBuffer>` |
| `getWritable` / `getReadable` chunks | `Uint8Array<ArrayBuffer>` |

- `write` / `read` use byte sequences (`Uint8Array<ArrayBuffer>`).
- Supports streamed reading and writing with `Uint8Array<ArrayBuffer>` chunks.
- Write streams append to a temporary key and atomically replace it with a rename on completion. With `ttl`, the expiration is attached after finalization.
- Read streams emit the fetched bytes as a single chunk.

## Errors [#errors]

This package throws the following errors.

### ClusterNotSupportedError [#error-cluster-not-supported]

Thrown when the constructor `cluster` option is specified.

#### Meaning

v1 only supports standalone mode; the `cluster` option is not supported.

#### How to fix

Omit the `cluster` option and connect to a standalone Valkey.

### InvalidCloseTimeoutError [#error-invalid-close-timeout]

Thrown when the constructor `closeTimeout` is not a finite positive number.

| Prop | Type | Default | Description |
| - | - | - | - |
| `actual` | `[#invalid-close-timeout-actual] unknown` | - | The received `closeTimeout` value. |

#### Meaning

`closeTimeout` was given something other than a finite positive number (in milliseconds).

#### How to fix

Specify a finite positive number (in milliseconds) for `closeTimeout`.

### InvalidTtlError [#error-invalid-ttl]

Thrown when the constructor `ttl` is not a finite positive number.

| Prop | Type | Default | Description |
| - | - | - | - |
| `actual` | `[#invalid-ttl-actual] unknown` | - | The received `ttl` value. |

#### Meaning

`ttl` was given something other than a finite positive number (in milliseconds).

#### How to fix

Specify a finite positive number (in milliseconds) for `ttl`.

### ConnectTimeoutError [#error-connect-timeout]

Thrown when the connection in `open()` times out.

| Prop | Type | Default | Description |
| - | - | - | - |
| `timeoutMs` | `[#connect-timeout-timeoutms] number` | - | The time (in milliseconds) until timeout. |

#### Meaning

The connection to Valkey was not established within `connectTimeout` (default `5000` ms).

#### How to fix

Check that the server is running and the connection URL is correct, and extend `connectTimeout` if needed.

### CloseTimeoutError [#error-close-timeout]

Thrown when disconnection in `close()` times out.

| Prop | Type | Default | Description |
| - | - | - | - |
| `timeoutMs` | `[#close-timeout-timeoutms] number` | - | The time (in milliseconds) until timeout. |

#### Meaning

Disconnection from Valkey did not finish within `closeTimeout`. The connection is disconnected and cleaned up.

#### How to fix

Check the server state, and extend `closeTimeout` if it keeps happening.

### KeyNotFoundError [#error-key-not-found]

A shared `@unikvs/core` error. Thrown when reading a missing key.

#### Meaning

The specified key does not exist. A shared `@unikvs/core` error.

#### How to fix

Check with `exists` before reading.

#### Example

The following example catches `KeyNotFoundError`.

```ts
import { KeyNotFoundError } from "@unikvs/valkey";

try {
  const data = await kvs.get("missing");
} catch (ex) {
  if (ex instanceof KeyNotFoundError) {
    console.log("Key not found");
  } else {
    throw ex;
  }
}
```
