WebSocket Server
The WebSocket server is implemented using Bun’s native WebSocket support insrc/index.ts.
Server Configuration
WebSocket Endpoint:ws://localhost:3000/ws
The server upgrades HTTP connections to WebSocket when clients connect to the /ws path:
src/index.ts:27-33
WebSocket Event Handlers
Connection Open (src/index.ts:54-67)
When a client connects:
New clients immediately receive all accumulated changes via the “initial” message type, ensuring they see the complete history.
Message Received (src/index.ts:50-53)
Currently, the server only logs client messages. This handler could be extended to support client commands like filtering or requesting specific data ranges.
Connection Close (src/index.ts:68-71)
Broadcasting Changes
Thebroadcast() function sends changes to all connected clients (src/index.ts:12-19):
src/index.ts:110-114):
WebSocket Client
The React frontend implements a robust WebSocket client with auto-reconnection insrc/App.tsx.
Connection Management
Initial Connection (src/App.tsx:44-46)
Connection State Tracking
The client maintains connection state via React hooks:src/App.tsx:19-21
Event Handlers
onopen (src/App.tsx:48-53)
onmessage (src/App.tsx:55-75)
The client handles two message types:
- initial: Complete history sent on connection
- change: Incremental updates for new database changes
onerror (src/App.tsx:77-82)
onclose with Auto-Reconnection (src/App.tsx:84-99)
Connection Lifecycle Management
The client prevents multiple concurrent connections (src/App.tsx:30-42):
Cleanup on Unmount (src/App.tsx:105-122)
The cleanup function uses close code 1000 to indicate normal closure, preventing auto-reconnection when the component unmounts.
Message Protocol
Server to Client Messages
Initial State Message
Sent when a client first connects:Change Event Message
Sent when database changes occur:Change Object Structure
Each change object includes:- operation: The SQL command type (INSERT, UPDATE, DELETE)
- table: Fully qualified table name with schema
- …columns: All column values from the affected row
For UPDATE operations, only the new values are included. For DELETE operations, the row data may be limited based on PostgreSQL’s REPLICA IDENTITY setting.
Connection Status UI
The UI displays real-time connection status (src/App.tsx:137-160):
Performance Characteristics
Server-Side
- Broadcasting Complexity: O(n) where n = number of connected clients
- Memory Usage: O(m) where m = total number of changes (unbounded growth)
- Connection Limit: Bounded by Bun’s WebSocket capacity
Client-Side
- Message Parsing: O(1) for individual messages
- State Update: O(k) where k = number of new changes per message
- Re-render: Optimized by React’s virtual DOM diffing
Best Practices
Connection Management
Always clean up WebSocket connections in React’s cleanup function to prevent memory leaks
Error Handling
Implement exponential backoff for reconnection attempts in production
Message Validation
Validate incoming messages with proper TypeScript interfaces
State Management
Use functional updates (
prev => ...) to avoid stale closure issuesPotential Enhancements
- Heartbeat Mechanism: Add periodic ping/pong to detect stale connections
- Message Acknowledgment: Implement ack system to ensure reliable delivery
- Client-Side Filtering: Allow clients to subscribe to specific tables or operations
- Compression: Use WebSocket compression for large change sets
- Authentication: Add token-based auth during WebSocket upgrade
- Rate Limiting: Prevent clients from overwhelming the server with messages
Related Topics
Architecture Overview
Understand the complete system architecture
Database Subscription
Learn how PostgreSQL changes are captured