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 ioredisProvide 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.