Definition
This is the sync pattern to use in collaborative/offline apps when you want "my typing to reflect on screen immediately without waiting for the server response," while also staying aligned with other people's changes and the server's final result. The core idea is to draw my change on screen first, but keep alongside it an exactly-reversible "inverse edit," so that when the server result later arrives, I briefly rewind my change, apply the server's first, then re-apply my change on top.
More precisely, Optimistic outbox rebase is where the client applies a patch (a change fragment that partially alters state) to local state first (optimistic, reflecting it in advance while betting on success) without waiting for the server response, then stores it as pending (waiting to be confirmed) in the outbox (a waiting queue collecting my not-yet-server-confirmed changes). When a remote patch arrives, it converges (everyone reaches the same result) by rolling back pending in reverse order → applying remote in authoritative (the final authority the server decides) order → forward re-applying pending. Each optimistic step must keep an inverse patch (the opposite edit that exactly reverses that change) alongside it, so rollback is possible. This process of rewinding and re-applying is called rebase.
Why it's needed
Collaborative / offline-first UX presumes "my typing reflects on screen immediately." But network latency, reordering, and conflicts make the local base (the state my screen took as its reference) diverge from server truth. A throw-only policy (just error out and discard on conflict) loses user edits, and a silent merge (quietly merging with no notice) makes debugging impossible. An outbox rebase with inverses is the practical middle ground between UX and convergence.
How it works
- Optimistic apply — generate
{ patches, inverse }, apply patches to state, push to outbox. - Remote arrive — apply remote patches in the order of the seq (sequence, the ordinal assigned per change) the server assigns as monotonic (monotonically increasing, only ever growing) (merge authority).
- Rebase
- apply inverse of pending in reverse order (rollback)
- apply remote patches in seq order
- forward-apply pending again (inverse may need recomputation)
- Dropped — re-apply failures (e.g. anchor deleted) are not swallowed but reported to the caller/UI.
| Role | Typical responsibility |
|---|---|
| seq | the single authority of merge order |
| HLC/timestamp | HLC (Hybrid Logical Clock, a clock mixing real time and a logical counter to order events) — audit / local-sort meta (not merge authority) |
| inverse | the fuel for rollback / rebase |
| tie-break | the rule that decides a deterministic order when seqs are equal (concurrent insert) |
Practical application
For order intent, a neighbor anchor (using the adjacent front/back items as reference points) + fractional position key (a decimal sort key you can insert infinitely between items) + client/op tie-break combination is more favorable to concurrent inserts than an integer index (0, 1, 2… integer indices).
Trade-offs
- Optimistic UI is fast but needs a conflict UI design (who won, dropped notifications).
- Inverse computation cost/correctness is a premise — an inverse bug is silent corruption after rebase.
- The implementation is lighter than CRDT/full OT (a full-blown collaboration algorithm that merges concurrent edits from many users without conflict), but the server seq policy and the client outbox contract must be rock-solid.
When not to use it
- Internal admin-only forms where every operation is server-authoritative and latency is acceptable (the optimistic gain is small).
- Domains where the inverse can't be trusted or patches are irreversible-only.
Common mistakes
- Doing optimistic only without storing inverse → rebase impossible.
- Merging by wall-clock timestamp alone → non-deterministic order.
- Silent drop on rebase failure → "my edit vanished — why?" is untraceable.
- Undo-stack recording left on during rebase → history pollution.
Related concepts
- two-stack-inverse-undo — inverse patch mental model
- fractional-index-ordering — anchor-based ordering
- race-safe-async-ui-requests — a similar concurrency problem with stale responses