Build on the supported package contract
Use @absolutejs/sync-bus-redis through its supported public entry points.
@absolutejs/sync-bus-redisv0.1.1betaData & SyncRedis pub/sub ClusterBus for @absolutejs/sync — cross-instance fan-out via PUBLISH/SUBSCRIBE. Sibling to @absolutejs/sync-bus-pg; faster fanout, better geo-replication story. Works with any Redis client (ioredis, node-redis, etc.) via a narrow tag-template interface.
bun add @absolutejs/sync-bus-redisRedis pub/sub ClusterBus for @absolutejs/sync. Sibling to @absolutejs/sync-bus-pg — same ClusterBus contract, different transport.
Docs: absolutejs.com/documentation/cluster-bus-overview#redis-adapter
Concern — sync-bus-redis — sync-bus-pg
Payload size — No cap — JSON through — 8KB NOTIFY cap (spill-table fallback)
Fan-out latency at 10+ subscribers — In-memory, low — WAL-replicated, higher
Geo-replication — Native (Redis Cluster, ElastiCache, Memorystore, Upstash) — Heavy ops (PG logical replication)
Delivery semantics — At-most-once (no message retention) — At-most-once (NOTIFY) + spill rows for oversized
Already in your stack? — If yes → win-win — If yes → win-win
The headline tradeoff. Redis is in-memory pub/sub — a subscriber that's disconnected when a message fires misses it. For cross-instance resume past shard reboot, pair with engine.exportChangeLog() / importChangeLog() (sync 1.19.0+) regardless of which bus you use.
Returns ClusterBus & { metrics() }. Pass to engine.connectCluster(bus).
bus.metrics()
Outcomes
Use @absolutejs/sync-bus-redis through its supported public entry points.
Hardening checklist
Follow in order
Working example for Usage with ioredis.
import { Redis } from 'ioredis';
import { createSyncEngine } from '@absolutejs/sync/engine';
import { createRedisClusterBus } from '@absolutejs/sync-bus-redis';
const publisher = new Redis(process.env.REDIS_URL!);
const subscriberClient = new Redis(process.env.REDIS_URL!);
// ioredis: a subscribed connection can't issue other commands.
// Bridge its EventEmitter API into our (channel, listener) shape:
const subscriber = {
subscribe: async (channel: string, listener: (msg: string) => void) => {
await subscriberClient.subscribe(channel);
const handler = (chan: string, msg: string) => {
if (chan === channel) listener(msg);
};
subscriberClient.on('message', handler);
return async () => {
subscriberClient.off('message', handler);
await subscriberClient.unsubscribe(channel);
};
},
};
const bus = createRedisClusterBus({ publisher, subscriber });
const engine = createSyncEngine({ instanceId: 'shard-A' });
await engine.connectCluster(bus);Working example for Usage with node-redis v4+.
import { createClient } from 'redis';
import { createRedisClusterBus } from '@absolutejs/sync-bus-redis';
const publisher = createClient({ url: process.env.REDIS_URL });
const subscriberClient = publisher.duplicate();
await Promise.all([publisher.connect(), subscriberClient.connect()]);
// node-redis: subscribe takes a callback directly.
const subscriber = {
subscribe: async (channel: string, listener: (msg: string) => void) => {
await subscriberClient.subscribe(channel, listener);
return async () => {
await subscriberClient.unsubscribe(channel);
};
},
};
const bus = createRedisClusterBus({ publisher, subscriber });Working example for API.
createRedisClusterBus({
publisher, // RedisPublisher — publish(channel, message)
subscriber, // RedisSubscriber — subscribe(channel, listener) → unsubscribe fn
channel?, // default 'absolutejs_sync_cluster'
onError?, // logger for parse / delivery failures
});Working example for bus.metrics().
{
published: number; // PUBLISH calls
received: number; // messages parsed + delivered to onMessage
publishErrors: number; // publisher.publish() rejections
subscribeErrors: number; // JSON.parse failures on incoming messages
totalSubscribersReached: number; // sum of counts Redis returned from PUBLISH
// — a drop to 0 when you expect peers signals
// subscriber disconnects (partition, restart)
}Supported entry points declared by this package manifest.
Package entry point declared in package.json.
Scripts declared by this package manifest.
Search the declarations exported by the current package type files. Expand a symbol to inspect its source-backed signature.
Minimal Redis publisher contract. Both ioredis and node-redis v4 structurally satisfy this (publish(channel, message) is the canonical signature; both return a Promise that resolves to the number of subscribers that received the message).
type RedisPublisher = {
publish: (channel: string, message: string) => Promise<number | unknown>;
};@absolutejs/sync-bus-redis