-
-
Notifications
You must be signed in to change notification settings - Fork 25
Open
Description
Problem
next-ws currently only supports single-instance deployments. When running multiple Next.js instances behind a load balancer (Docker Compose + Traefik, Kubernetes, etc.), WebSocket messages only reach clients connected to the same instance. There's no way to broadcast messages across instances.
Proposed Solution
Add an optional adapter interface that allows users to implement their own pub/sub mechanism (Redis, RabbitMQ, Kafka, etc.) for cross-instance communication.
Implementation Requirements
1. Add adapter interface (~15 lines):
// src/server/adapters/adapter.ts
export interface Adapter {
broadcast(room: string, message: unknown): Promise<void>;
onMessage(room: string, handler: (message: unknown) => void): void;
close(): Promise<void>;
}2. Modify setupWebSocketServer in src/server/setup.ts (~30 lines):
- Add optional
options?: { adapter?: Adapter }parameter - When adapter is provided:
- Subscribe to adapter messages and forward to local clients
- Forward local client messages to adapter for broadcast
- When adapter is NOT provided, behavior is unchanged (backward compatible)
3. Export from src/server/index.ts:
export type { Adapter } from './adapters/adapter.js';Benefits
- Zero breaking changes: Existing code works identically without an adapter
- No new dependencies: Users bring their own Redis/RabbitMQ client
- Flexible: Users can implement encryption, compression, rate limiting in their adapter
- Out of scope for next-ws: You don't maintain Redis connection logic or debug broker issues
Example User Implementation
import { setupWebSocketServer, type Adapter } from 'next-ws/server';
import Redis from 'ioredis';
class RedisAdapter implements Adapter {
private pub = new Redis(process.env.REDIS_URL);
private sub = new Redis(process.env.REDIS_URL);
async broadcast(room: string, message: unknown) {
await this.pub.publish(room, JSON.stringify(message));
}
onMessage(room: string, handler: (msg: unknown) => void) {
this.sub.subscribe(room);
this.sub.on('message', (channel, msg) => {
if (channel === room) handler(JSON.parse(msg));
});
}
async close() {
await Promise.all([this.pub.quit(), this.sub.quit()]);
}
}
setupWebSocketServer(nextServer, { adapter: new RedisAdapter() });Related Issues
- Persistence and multi instance setup #10 asked about multi-instance support (closed as out of scope)
- [Documentation] Exposing
WebSocketServerfor server-side access #20 documented accessing WebSocketServer globally
This approach keeps multi-instance complexity out of next-ws core while enabling users who need horizontal scaling.
EinMelih, Kernoterikt, 0-don and RICHIE-Coding
Metadata
Metadata
Assignees
Labels
No labels