---
title: Realtime providers
description: Select local filesystem or Redis storage for replay, fanout, and presence.
pagination: false
sidebar:
  icon: plug
---

Select a realtime provider to carry channel events between your backend and connected clients. Agent threads use the separate `agent-state` capability, and ordinary caching continues to use `cache`. Configure only the capabilities your application needs.

## Pre-setup

Use Redis in local Docker for replay, fanout, and presence. Start from an existing RELKIT app and a running Docker daemon.

1. **Install Redis and Docker support**

    {/* Generated by apps/docs/scripts/generate.ts. Do not edit. */}

    From this guide's application/package root, install only its selected requirements:

    ```sh
    bun add @relkit/docker@0.7.12 @relkit/redis@0.8.1
    ```

    Keep these owner-specific versions and the lockfile together. Runtime SDKs belong in `dependencies`; build/type tooling belongs in `devDependencies`. Installing an adapter does not supply its optional SDK peers or enable the feature's configuration.

2. **Configure the default realtime profile**

    > **Merge with your application**
    >
    > The root configuration helper is [`defineApp`](/docs/learn/concepts/application), not
    > `defineConfig`. Merge the capability entries below into your existing `relkit.config.ts`; keep its
    > ID, environment, profiles, and other settings. The empty `defineEnv({})` in a standalone example
    > means this local provider needs no application variables. Keep your existing environment contract.

    ```ts title="relkit.config.ts"
    /** Channels use Docker Redis by default during local development. */
    import { defineApp, defineEnv } from "@relkit/app/config";
    import { docker } from "@relkit/docker";
    import { redisRealtime } from "@relkit/redis";

    export default defineApp({
      env: defineEnv({}),
      realtime: docker(redisRealtime()),
      defaults: { realtime: "default" },
    });
    ```

    Channels without `profile` use `default`. Docker supplies Redis's connection values, so there
    are no additional application environment fields. Agent checkpoints need the separate
    [agent-state configuration](/docs/modules/ai#pre-setup).

3. **Check and start after declaring a channel**

    Check Docker before continuing. After adding the resource and its service registration, run from the app root:

    ```sh title="Terminal — application root"
    docker version
    bun run check
    bun run typecheck
    bun run dev
    ```

    `check` validates the graph; it starts no containers. `dev` starts only Docker recipes used by
    that graph, waits for readiness, and binds their generated connection values. An unused profile
    alone does not start a container. Keep the server running and use `bun run relkit local status`
    in another terminal to inspect the services. [Local Docker](/docs/modules/integrations/local-docker)
    covers detached startup and stopping services while retaining their volumes.

## Choose a provider

| Provider                  | Best fit                                                   | Replay and fanout                                                  | Durability                                 |
| ------------------------- | ---------------------------------------------------------- | ------------------------------------------------------------------ | ------------------------------------------ |
| `docker(redisRealtime())` | Default local development                                  | Pinned Redis recipe with retained streams and presence             | Persistent Docker volume                   |
| `redisRealtime()`         | Connected Redis; multiple application or gateway instances | Redis Streams read independently by every gateway; shared presence | Depends on Redis persistence configuration |
| `localRealtime()`         | Optional one-machine workflow without Docker               | Filesystem-backed retained state with bounded polling              | Local filesystem                           |

The local provider keeps state under `.relkit/state` by default. Its wait loop polls every 250 ms, so another process can make progress even when filesystem notifications are unavailable. Use its `root` option only when the application needs a different state directory.

Redis uses a stream reader per gateway. Do not replace this with one shared consumer group: consumer groups distribute records among gateways, while realtime fanout requires every gateway with interested subscribers to see the event.

## Alternative provider configuration

**Local filesystem**

The minimal app installs no realtime profile automatically. For one-machine filesystem state,
install the local owner, import `localRealtime` and select a matching `defaults.realtime` profile:

{/* Generated by apps/docs/scripts/generate.ts. Do not edit. */}

From this guide's application/package root, install only its selected requirements:

```sh
bun add @relkit/local@0.7.12
```

Keep these owner-specific versions and the lockfile together. Runtime SDKs belong in `dependencies`; build/type tooling belongs in `devDependencies`. Installing an adapter does not supply its optional SDK peers or enable the feature's configuration.

**Connected Redis**

For a connected Redis provider, select its owner instead and supply the configured Redis connection:

{/* Generated by apps/docs/scripts/generate.ts. Do not edit. */}

From this guide's application/package root, install only its selected requirements:

```sh
bun add @relkit/redis@0.8.1
```

Keep these owner-specific versions and the lockfile together. Runtime SDKs belong in `dependencies`; build/type tooling belongs in `devDependencies`. Installing an adapter does not supply its optional SDK peers or enable the feature's configuration.

Only a Docker-backed Redis selection also needs `@relkit/docker` and a running daemon; use the
[local Redis setup](/guides/caching/cache-product-prices#configure-caching) for that choice. Agent state is a
separate capability; channels alone do not require `@relkit/langchain` or a model SDK.

The commerce application configures distinct Redis-backed realtime, agent-state, and cache capabilities:

```ts title="examples/commerce/relkit.config.ts"
realtime: docker(redisRealtime({ url: binding.secret("REALTIME_REDIS_URL") })),
"agent-state": {
  agents: docker(redisAgentState({ url: binding.secret("AGENT_STATE_REDIS_URL") })),
},
```

`defaults.realtime` selects the profile used by channels that omit `profile`. A channel can name another profile when one application needs different retention, tenancy, or infrastructure boundaries.

## Understand acknowledgements and resets

`trigger()` acknowledges an atomic provider append and receipt, not delivery to browser tabs. Redis durability is only as strong as the selected Redis persistence and replication settings. Document that deployment choice rather than describing every Redis-backed append as durable.

Each provider exposes an epoch. If retained state is lost or replaced, the epoch changes. Old checkpoints then produce a recovery gap, and missing idempotency receipts are reported as state loss rather than permission to retry an uncertain publish automatically.

## Capacity and overload

RELKIT enforces per-record and aggregate limits for encoded event size, retained bytes, active partitions, live connections, subscriptions, presence members, and receipt retention. Per-principal limits return a typed 429 response; application or provider capacity returns a typed 503 response.

Existing unrelated work is not evicted to admit a new partition or event. Tune provider capacity and retention together: longer replay windows consume more storage, while authoritative route recovery makes short windows safe.

## Production checklist

- Use `redisRealtime()` when subscriptions must survive or fan out across application instances.
- Configure Redis persistence and replication to match the acknowledgement guarantee your product needs.
- Monitor provider resets, rejected appends, slow consumers, expired grants, connection counts, and retained bytes.
- Keep WebSocket upgrades and streaming responses enabled through the generated server and proxy path.
- Configure exact browser origins and credentialed CORS explicitly.

{/* Generated by apps/docs/scripts/generate.ts. Do not edit. */}

**Reference and source**

- [`@relkit/realtime` API](/docs/api/realtime)
- [`@relkit/client` API](/docs/api/client)

- [`examples/commerce/relkit.config.ts`](https://github.com/rel-kit/relkit/blob/main/examples/commerce/relkit.config.ts)
