Designing Snapshot and Delta APIs
The server's side of real-time sync: what a snapshot must carry, what a delta must say, how sequence numbers and resync work, and why edits should share the snapshot's shape.
On this page
I’ve written about consuming snapshots and deltas on the 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 dashboards at a fintech, traced back to decisions on the server. This note is the other side: what I’d ask of an API that streams live state.
The snapshot
A snapshot is the full current state of whatever the client is looking at. It should carry:
- A sequence number or version. Without it the client can’t tell which deltas are already included. This is the single most important field.
- Everything needed to render, including metadata that rarely changes (column definitions, units, precision), so the client doesn’t stitch together several calls before it can paint.
- Stable identifiers for every entity, so deltas can target them.
And it should be cheap to ask for again. Resync is a normal operation, not an emergency.
The delta
A delta says what changed since a version. It should:
- Carry its own sequence number, strictly increasing per stream.
- Express add, update and remove explicitly. Update-only streams leave ghost rows behind when something disappears.
- Be granular. Send the fields that changed, keyed by entity id. If a tiny change to one field re-sends a large payload, every client re-renders far more than it should. I watched a whole screen re-render because a big snapshot changed by one value.
- Be idempotent to apply. Applying the same delta twice should do no harm, because retries and reconnects happen.
Gaps and resync
Clients will miss messages: a reconnect, a sleeping laptop, a slow consumer. The protocol should make recovery mechanical:
- The client notices a gap in sequence numbers.
- It asks for a fresh snapshot (or for deltas since its last good version, if the server keeps a short history).
- It discards anything older than the new base and carries on.
If the server can’t replay history, say so, and let the client fall back to a snapshot. That’s the same idea as a database replica catching up from a log, or rejoining a cluster in Raft.
Snapshot vs delta: when to send which
- Deltas when changes are small relative to the state and frequent. They save bandwidth and client work.
- Periodic snapshots when state is small, or when deltas are hard to compute correctly. A snapshot is self-healing: any missed message is fixed by the next one.
- Both, commonly: a snapshot on subscribe and on request, deltas in between, and perhaps a periodic snapshot as a safety net.
Edits should look like snapshots
When users can edit live data, the write path matters as much as the read path. The pattern that saved the most bugs: edits use the same shape as the snapshot, keyed by the same ids, and the server answers with the new version. Then the client can compare its pending edits to the latest snapshot field by field, and the server can validate an edit against a known version (rejecting it if the base has moved on, or merging if that’s safe). Designing for audit and deltas from the start (who changed what, from which version) makes both concurrency and debugging far easier.
Backpressure on the server
A server streaming to many clients has to decide what to do when one falls behind. Options: buffer (with a limit), conflate (send only the latest value per entity instead of every intermediate one), or drop the client back to snapshot mode. For prices and positions, conflation is usually right: a slow client needs the latest state, not every step in between. More on that in The Node.js Event Loop, Streams and Backpressure.
Related: WebSockets · Server-Sent Events (SSEs) · Message Delivery Semantics · REST API Design Trade-offs: Bulk Deletes, Request Bodies and Cancellation
- #websockets
- #api-design
- #real-time
- #sequence-numbers
- #event-streams
↩ Linked from (3)
…olling, 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. Incremental migrations, from a TypeScript cl…
Related: Designing Snapshot and Delta APIs · REST API Design Trade-offs: Bulk Deletes, Request Bodies and Cancellation
…nt is conflation: when a client falls behind, send it the latest state rather than every intermediate update (Designing Snapshot and Delta APIs).
↪ Links to (7)
Related by topic
- Growingcase study
A Resumable CMS Migration Tool
Distributed systems - Seed
Kubernetes
Platform engineering - Growing
Resumable Batch Migrations
Distributed systems - Growing
Heartbeat
Distributed systems