Real-Time Patterns

Building real-time features means solving problems that developers have encountered many times before. Rather than reinventing solutions, you can apply proven patterns that handle common scenarios effectively. Understanding these patterns helps you choose the right approach for your specific use case.

Presence Tracking

Presence shows who's currently online in your application — think of the green dots in Slack or the "typing..." indicators in chat apps.

The standard approach uses heartbeats. Clients send periodic pings to the server (typically every 30 seconds). If the server doesn't receive a heartbeat within a timeout period, it marks that user as offline and broadcasts the change to interested parties.

// Client sends heartbeat
setInterval(() => {
    ws.send(JSON.stringify({ type: 'heartbeat' }));
}, 30000);

// Server tracks last seen time
// If no heartbeat for 60 seconds, mark offline

This pattern handles network hiccups gracefully — a single missed heartbeat doesn't immediately show someone as offline.

Collaborative Editing

When multiple users edit the same document simultaneously, you need strategies to handle conflicts. Two main approaches dominate this space.

Operational Transform (OT) transforms operations based on what others have done. If Alice inserts "hello" at position 5 while Bob deletes character 3, OT adjusts Alice's operation to account for Bob's deletion.

CRDTs (Conflict-free Replicated Data Types) use data structures that mathematically guarantee consistency without coordination. Libraries like Yjs and Automerge implement CRDTs, making collaborative editing much more accessible.

For most applications, using an existing library beats building your own conflict resolution.

Live Updates

Real-time dashboards and feeds need efficient update mechanisms. The server pushes changes as they happen, and clients update their UI accordingly.

Consider throttling and batching for high-frequency updates. If your stock ticker updates 100 times per second, batching updates every 100ms provides a better user experience than overwhelming the UI.

// Batch updates
let pendingUpdates = [];
setInterval(() => {
    if (pendingUpdates.length > 0) {
        updateUI(pendingUpdates);
        pendingUpdates = [];
    }
}, 100);

Notifications

Push notifications to specific users require user-specific channels. Each user subscribes to their own notification channel, and the server publishes to that channel when something relevant happens.

For users who are offline when notifications arrive, store notifications in a database and deliver them when the user reconnects. Implement acknowledgment so you know which notifications were successfully received.

Combining Patterns

Real applications often combine multiple patterns. A collaborative document editor might use CRDTs for editing, presence for showing who's viewing, and notifications for mentions. Start with the simplest pattern that solves your problem, then add complexity as needed.

See More

Further Reading

You need to be signed in to leave a comment and join the discussion