In this lesson, you will learn how to use Redis Streams to ensure that new WebSocket clients receive the complete history of events they missed while offline.
The Synchronization Problem
When a client connects to a WebSocket server, they typically only receive events that occur after the handshake is complete. If a user temporarily loses connectivity or refreshes their browser, they miss the state transitions that happened in the interim. While you could store the entire state in a database, a Redis Stream acts as an append-only log that is purpose-built for replaying a sequence of events.
How Redis Streams Work
A Redis Stream is like a messaging queue that keeps a persistent history. When an event (like a chat_message or price_update) occurs, you append it to the stream using XADD.
When a new client connects, you don't just "handshake" them; you query the stream from the last ID they received. This allows the client to "catch up" to the current state of the application.
Implementation Pattern
Here is how you might handle a new client connection by replaying missed events:
// On WebSocket connection
socket.on('connection', async (client) => {
const lastEventId = client.handshake.query.lastId || '0';
// Read events from the stream starting after the client's last known ID
const history = await redis.xread('STREAMS', 'events_stream', lastEventId);
// Send the missed events to the client
history[0][1].forEach(([id, data]) => {
client.emit('event', JSON.parse(data.payload));
});
});
// When a new event happens, append it to the stream
async function broadcast(event) {
const payload = JSON.stringify(event);
await redis.xadd('events_stream', '*', 'payload', payload);
io.emit('event', event);
}
By using XREAD, we request all entries with an ID greater than the one the client provides. If the client has never connected, we pass 0 to retrieve the entire stream (or a capped subset if you use MAXLEN to prune old data). This ensures that the client-side state machine is perfectly synchronized with the server's event log without requiring a full database pull.
Key Takeaway: Redis Streams provide a persistent, ordered log of events that allows disconnected clients to catch up to the current state by replaying missed messages since their last known ID.