Browse documentation

Realtime with Redis

Share FlowPanel realtime events across Next.js instances and external workers.

Use this recipe after deciding that the single-process memory driver is insufficient. It keeps the browser SSE route unchanged and replaces the process-local publisher with Redis pub/sub.

Install Redis support

pnpm add ioredis

Provide REDIS_URL through the deployment environment. Use TLS and credentials appropriate for the Redis provider.

Configure the publisher

export default defineAdmin({
  adapter,
  auth,
  realtime: {
    driver: "redis",
    url: process.env.REDIS_URL,
    keyPrefix: "myapp-production",
  },
  resources,
});

Use a distinct key prefix for every application and environment sharing the same Redis service. Resources or widgets subscribe to their normal application channel names; the prefix is applied on the transport.

Publish from an external worker

A worker, a cron job or a one-off script publishes through @flowpanel/kit/publish. It is the whole realtime client: no admin config, no adapter, no Next.js — one connection and the wire format.

import { createPublisher } from "@flowpanel/kit/publish";

const events = createPublisher({ redis: process.env.REDIS_URL! });

await events.publish(events.channelFor("orders"), { action: "update", id: orderId });
await events.close();

channelFor("orders") returns resource.orders, the channel a resource subscribes to when it sets realtime: true; any other string is a channel of your own. Use the same keyPrefix the admin uses, or neither side sees the other:

const events = createPublisher({ redis: process.env.REDIS_URL!, keyPrefix: "myapp-production" });

Create the publisher once per process and close() it on shutdown. A publish-only process opens exactly one connection, on the first publish — nothing connects while the module is merely imported.

When the worker already owns a configured Redis client — TLS, a sentinel, a retry strategy, a BullMQ connection — hand that over instead of a URL, and it stays yours to close:

import { createPublisher } from "@flowpanel/kit/publish";
import { redis } from "./redis";

const events = createPublisher({ redis });

Inside the admin itself nothing changes: ctx.publish in an action, or publishResource from @flowpanel/kit/server, already use the publisher defineAdmin configured.

Verify across instances

Run two application instances against the same Redis key prefix. Connect a browser to one, perform a mutation through the other, and confirm the browser refetches. Repeat with a worker publication. If local same-instance updates work but this test fails, inspect the prefix, the Redis URL, and network/TLS settings. FlowPanel also warns on startup when it resolves the memory driver while REDIS_URL is set in the environment, which is the configuration that produces exactly this symptom.

Production notes

Redis publication distributes refresh signals; it does not make SSE durable. Monitor publish errors and reconnects, and decide whether a failed post-commit notification should alert, retry, or wait for the next user refresh.

Return to the full Realtime production checklist.