A high-performance, event-driven WebSocket notification system built with the ws
package and Redis pub/sub, designed for horizontal scalability.
The system implements an event-driven architecture where each WebSocket connection is treated as an independent event emitter/listener, allowing for non-blocking I/O operations and high concurrency.
- Event-Driven Architecture: Non-blocking I/O operations using Node.js event emitters
- Horizontal Scalability: Multiple server instances can handle increasing load
- Real-time Communication: Core WebSocket (
ws
) implementation for efficient bi-directional communication - Connection Management: Robust user session tracking and management
- Message Broadcasting: Redis pub/sub for cross-instance message distribution
- TypeScript: Type-safe implementation with improved developer experience
- WebSocket: Core
ws
package for lightweight and efficient WebSocket implementation - Redis Pub/Sub: For cross-instance message broadcasting
- Express: HTTP server for WebSocket upgrade handling
- TypeScript: For type safety and better code organization
import { WebSocket, WebSocketServer } from "ws";
const io = new WebSocketServer({
noServer: true,
path: "/notification",
});
// Event-driven connection handling
io.on("connection", async (socket: WebSocket) => {
// Connection events
});
// Message event handling
socket.on("message", async (data: Buffer) => {
const message = data.toString();
const redisClient = await getRedisClient();
await redisClient.publish("channel", message);
});
// Connection cleanup
socket.on("close", async () => {
userManager.disconnect(socket);
});
// Message event handling from other servers
this.redisClient = redis.createClient({
url:process.env.REDIS_URL || "redis://default:password@localhost:6379"
});
const subscriber = this.redisClient.duplicate();
await subscriber.connect();
await subscriber.subscribe('channel', (message: string) => {
message = JSON.parse(message);
console.log("redis message: ",message);
});
-
Horizontal Scaling
- Multiple server instances can run simultaneously
- Load balancer distributes WebSocket connections
- Redis pub/sub ensures message delivery across instances
-
Connection Management
- User Manager tracks active connections
- Efficient cleanup on disconnection
- Session persistence across server restarts
-
Performance Optimization
- Non-blocking I/O operations
- Efficient message broadcasting
- Connection pooling for Redis
-
Prerequisites
Node.js >= 14 Redis Server TypeScript >= 4.x
-
Installation
# Clone repository git clone <repository-url> # Install dependencies npm install # Configure environment cp .env.example .env
-
Configuration
REDIS_URL=redis://localhost:6379 WS_PORT=3000
-
Running the Server
# Development npm run dev # Production npm run build npm start
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature
) - Commit changes (
git commit -m 'Add amazing feature'
) - Push to branch (
git push origin feature/amazing-feature
) - Open a Pull Request