Snapshot and Delta Sync over WebSockets
Keeping a live screen correct under streaming updates: subscribe and buffer first, load a snapshot, apply only newer deltas by sequence number, and never let an incoming update overwrite what the user is editing.
Most real-time screens are fed two ways: a snapshot (the full state, once) and a stream of deltas (what changed since). Getting them to agree is harder than it looks, and much harder when a user is editing the same data that’s streaming in. I spent a good part of 2026 on exactly this, building trading dashboards at a fintech.
The sync recipe
- Subscribe first and buffer. Open the stream and queue deltas before you ask for the snapshot, so nothing slips through the gap between the two.
- Load the snapshot. It should carry a sequence number (or version).
- Drop buffered deltas older than the snapshot, apply the rest in order, then switch to applying deltas live.
- Only ever apply newer values. Every update carries a sequence; anything stale or out of order is ignored.
- Deltas need add, update and remove, not just update, or rows quietly linger.
- A new snapshot resets the base. Don’t try to turn snapshots back into deltas on the client; that’s the server’s job.
It’s the same idea as replaying a log after restoring a backup, and closely related to how consensus systems keep replicas in step (Message Passing).
Editing while data streams: pristine and dirty
The real trap is a user typing into a cell while the server keeps updating it. The pattern that worked:
- Keep a pristine copy (the latest server state) and a set of dirty fields (the user’s edits).
- Incoming deltas update pristine, never a dirty field, so a local edit is never overwritten mid-thought.
- Clearing an edit falls back to pristine. Submitting sends the diff between edits and pristine.
- Reset goes back to the latest live state, not a stale copy from when the page loaded.
- After submitting, refetch or invalidate so the next snapshot is the source of truth.
- Keep edits in the same shape as the snapshot; mismatched shapes are where the bugs hide.
Implementation tips
- Apply deltas near the grid (as grid transactions), not at the app root, and batch them on a short interval (AG Grid Performance Patterns).
- Index rows in maps by id: O(1) lookups instead of searching arrays on every message.
- One owner per socket. A single provider holds the connection; components subscribe to slices, so re-renders don’t tear down subscriptions (Zustand Transient Updates).
- Split big payloads into entities. A large snapshot that changes by one field shouldn’t re-render the whole screen.
Related: WebSockets · Server-Sent Events (SSEs) · Finding React Re-render and Memory Leaks
- #websockets
- #real-time
- #state-management
- #sequence-numbers
- #editing
↩ Linked from (4)
- AG Grid Performance PatternsGrowing
Related: Snapshot and Delta Sync over WebSockets · Finding React Re-render and Memory Leaks · Zustand Transient Updates
…client: subscribe and buffer, load a snapshot, apply newer deltas, never overwrite what the user is editing (Snapshot and Delta Sync over WebSockets). Most of the pain I hit on the client in 2026, building trading dashb…
…used; refs are for references, not global state. One owner per socket, with components subscribing to slices (Snapshot and Delta Sync over WebSockets). Suspend API polling when the user leaves the page or the tab is hidd…
…. Real-time protocols. WebSockets, SSE, polling, and the snapshot-and-delta sync behind live trading screens (Snapshot and Delta Sync over WebSockets, Designing Snapshot and Delta APIs). Migrations without big bangs. Inc…
↪ Links to (6)
Related by topic
- Growing
REST API Design Trade-offs: Bulk Deletes, Request Bodies and Cancellation
Backend - Growing
The Node.js Event Loop, Streams and Backpressure
Backend - Growingcase study
A Resumable CMS Migration Tool
Distributed systems - Seed
Kubernetes
Platform engineering