---
head:
  - - meta
    - name: description
      content: Use @tsed/adapters-redis with Ts.ED.
---
# Adapters Redis

`@tsed/adapters-redis` provides Redis-backed adapter implementations for Ts.ED adapter workflows.

## Installation

::: code-group

```sh [npm]
npm install --save @tsed/adapters-redis @tsed/redis redis
```

```sh [yarn]
yarn add @tsed/adapters-redis @tsed/redis redis
```

```sh [pnpm]
pnpm add @tsed/adapters-redis @tsed/redis redis
```

```sh [bun]
bun add @tsed/adapters-redis @tsed/redis redis
```

:::

## Exports

-   `RedisAdapter`
-   `OIDCRedisAdapter`
-   `RedisAdaptersSettings` (global `TsED.AdaptersOptions` extension)

## Adapter Options

Common options used with `Adapters.invokeAdapter(...)`:

-   `connectionName`: Redis connection name (default: `default`)
-   `useHash`: store payload using hash strategy (used for OIDC consumable models)
-   `keyPrefix`: prefix applied to all keys generated by the adapter (entity keys, index keys, OIDC keys)

```typescript
const adapter = adapters.invokeAdapter({
  adapter: RedisAdapter,
  collectionName: "client",
  model: Client,
  keyPrefix: "tests:e2e:run-42"
});
```

## Redis Module Configuration

`@tsed/adapters-redis` uses connections provided by `@tsed/redis`.

### Single Connection

```typescript
import {Configuration} from "@tsed/di";
import "@tsed/redis";

@Configuration({
  redis: [
    {
      name: "default",
      url: "redis://localhost:6379"
      // or socket: {host: "localhost", port: 6379}
    }
  ]
})
export class Server {}
```

### Cluster

```typescript
import {Configuration} from "@tsed/di";
import "@tsed/redis";

@Configuration({
  redis: [
    {
      name: "default",
      nodes: [{url: "redis://localhost:7000"}, {url: "redis://localhost:7001"}, {url: "redis://localhost:7002"}]
    }
  ]
})
export class Server {}
```

### Sentinel

`@tsed/redis` (node-redis integration) currently documents and implements single + cluster modes.
If you need Sentinel-specific behavior today, prefer `@tsed/adapters-ioredis` / `@tsed/ioredis`.

## Typical Use Case

Used mainly with OIDC provider persistence, where adapter models (tokens, grants, codes) are stored in Redis.

```typescript
import {OIDCRedisAdapter, RedisAdapter} from "@tsed/adapters-redis";
```

## Test Isolation

When tests run in parallel, prefer `keyPrefix` isolation over Redis DB index rotation:

```typescript
import {randomUUID} from "node:crypto";
import {Adapters} from "@tsed/adapters";
import {OIDCRedisAdapter} from "@tsed/adapters-redis";
import {DITest, inject} from "@tsed/di";
import {Property} from "@tsed/schema";
import {TestContainersRedis} from "@tsedio/testcontainers-redis";
import {beforeAll, beforeEach, afterAll, afterEach, describe, expect, it} from "vitest";

class AuthorizationCode {
  @Property()
  _id: string;

  @Property()
  uid: string;
}

describe("OIDC adapter isolation", () => {
  let keyPrefix: string;

  beforeAll(() => TestContainersRedis.startContainer());

  beforeEach(() => {
    keyPrefix = `test:${randomUUID()}`;
    return DITest.create({
      redis: [
        {
          name: "default",
          ...TestContainersRedis.getRedisOptions()
        }
      ]
    });
  });

  afterEach(() => DITest.reset());
  afterAll(() => TestContainersRedis.stopContainer());

  it("isolates data per test", async () => {
    const adapter = inject(Adapters).invokeAdapter<AuthorizationCode>({
      adapter: OIDCRedisAdapter,
      collectionName: "AuthorizationCode",
      model: AuthorizationCode,
      keyPrefix
    });

    await adapter.create({uid: "u1"});
    const items = await adapter.findAll();
    const keys = await (adapter as any).db.keys(adapter.prefix("AuthorizationCode:*"));

    expect(items.length).toBe(1);
    expect(keys.length).toBe(1);
    expect(keys[0]).toContain(adapter.prefix("AuthorizationCode:"));
  });
});
```
