Skip to content
RELKIT
Esc
↑↓navigate↵open⌘Jpreview
On this page

Realtime providers

Select local filesystem or Redis storage for replay, fanout, and presence.

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.

Install Redis and Docker support

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

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.

Configure the default realtime profile

/** 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.

Check and start after declaring a channel

Check Docker before continuing. After adding the resource and its service registration, run from the app 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 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

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:

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

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.

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

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

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 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:

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.
Reference and source