skip to content

What does an optimistic update write into the cache before the server answers, and what does it need to roll back?

level: middleimportance: must knowfreq 64%

answer

  1. render the prediction, keep the way back
  2. previous value, scoped to what you touched
  3. a patch needs an identity, not just a value
  4. the response is the authority on success
  5. an ordered patch list survives a second write

basics

~20 s

An optimistic update patches the cached copy with the client's predicted result before the request settles. Rollback needs the previous value of exactly the entries it touched plus the patch's own identity; success needs reconciliation with the server's representation.

solid answer

~50 s

Optimistically, the component writes the predicted change into the local copy the view reads before the server has agreed, so the change appears at render speed rather than network speed. Three things make that safe. First, only predict what the client can compute — a flag flipped, text the user typed — not a server-generated identifier or a recomputed total. Second, capture the previous value of exactly the entries the patch touches, and give the patch an identity: a second write to the same entity can arrive while the first is pending, and a blind restore of a saved value would reinstate something the later patch already replaced. Third, on success reconcile with what the server returned instead of keeping the guess. An optimistic value is a prediction with a rollback plan, never a substitute for the response.

go deeper

for a junior

Remember the shape: show the change now, send the request, undo if it fails. The undo is the part interviewers listen for, so never describe optimism without describing the way back.

for a middle

Explain what is captured at patch time and why the scope matters — the previous value of the entries you touched, plus an identity for the patch — and why the response replaces your prediction on success.

for a senior

Demonstrate the failure modes you have actually hit: a rollback clobbering a newer edit, a temporary identifier escaping into a follow-up write, a prediction the server was always going to recompute.

for a principal

Own the policy question. Per-write patch and reconcile logic is code and tests; decide which writes earn it, and treat a high rollback rate as evidence the client was predicting something it does not own.

## The trade optimism makes An optimistic update writes the **predicted** result of a change into the local copy the view reads, immediately, and only then sends the request. The user sees the change at the speed of a render instead of the speed of a round trip. The trade is explicit: you are rendering a value the server has not confirmed, so you owe the UI a way back. Three decisions have to be made before the request leaves. ## 1. What may be predicted Patch only what the client can compute correctly: - a boolean flipped on a row; - a field replaced with text the user just typed; - an item removed from, or appended to, a list the client already holds in full. As soon as the result depends on something the server owns — a generated identifier, a server clock, a total recomputed across rows the client never loaded, a permission decision, a position under the server's sort — the patch is a guess, and a wrong guess is a rollback the user watches happen. ## 2. The undo material To reverse a patch you need the previous value of exactly the entries it touched, captured at the moment of patching, **plus an identity for the patch itself**. Scope is what separates a working rollback from a data-losing one: | rollback approach | how it undoes | with a second write pending | | --- | --- | --- | | restore a saved copy of the whole cache | replaces everything | discards unrelated data that arrived meanwhile | | restore the saved previous value of the patched entries | replaces those entries | can reinstate a value the later patch already replaced | | keep pending patches in an ordered list, remove yours, re-derive | recomputes from the base value | the later patch survives — the robust form | The third row is why a patch needs an identity. The value the view reads becomes *the base value from the server, plus the pending patches applied in order*. Rollback removes one element from that list and re-derives; success removes it too, because the base value has caught up. Nothing else in the tree has to know a rollback happened. ## 3. Reconciling on success When the write succeeds, prefer the server's representation to your prediction: - it carries values the client cannot compute — identifiers, timestamps, derived counters, a canonical ordering; - it may have normalised what was sent (trimmed text, coerced a type, applied a default); - it is the value every later read will agree with, so keeping the guess leaves the cache quietly divergent until something refetches. If the response is partial, patch only the fields it actually states and treat the rest as unknown rather than cleared. If the response is empty, you have no reconciliation material at all and the entry has to be refetched to be trustworthy. ## The identifier problem An optimistic create has nothing the server has minted yet. The standard shape is: assign a temporary local key, render the row under it, and swap it for the real one when the response lands. The risk is what the user can do in between — opening the new item, or starting a second write that references it. Either hold those actions until the real identifier arrives, or re-point them when it does; a follow-up write sent against a temporary key will be rejected by a server that has never heard of it. ## Where reactivity models diverge The bookkeeping is the same everywhere, but who notices the patch is not. A runtime that re-runs the component function on every state write re-reads the derived value and produces a new render; one with fine-grained tracking notifies only the expressions that read the patched field; a compile-time reactive model has already rewritten those reads into subscriptions. The practical consequence is only about granularity — how much of the screen re-renders when a patch is applied and removed — not about whether the patch, the previous value and the identity are needed. ## Making a rollback tolerable Rollbacks are rare but memorable, so design the one the user will see: - explain it. A value that silently reverts reads as a bug; the same revert with a short failure message reads as a system that told the truth. - keep the control usable, so the obvious next action — try again — is available where the change happened. - avoid optimism where the reverted element is under the user's pointer and about to be pressed again, and where the user may already have acted on the predicted state. - watch how often it happens. A patch that rolls back regularly is a prediction the client should not have been making.

  • Why reconcile with the response when the optimistic value already looks right?
    Because the server owns fields the client cannot predict — identifiers, timestamps, derived counters, a canonical order — and may normalise what was sent. Keeping the guess leaves the cache divergent from what every later read will return, and the user may act on a value that was never real, such as opening an item under an invented identifier.
  • How do you roll back when the user has already changed the same entry again?
    Do not restore the value you saved: that reinstates what the later change replaced. Remove your patch from the ordered list of pending patches and re-derive the visible value from the base plus the patches that remain. The later change survives, and the view updates without knowing which patch disappeared.
  • What does an optimistic create do about the identifier the server has not issued yet?
    Render the new row under a temporary local key and swap it for the server's when the response lands. Anything the user starts against the temporary key — navigating to the item, or a second write referencing it — has to be held until the real identifier arrives or re-pointed once it does, because the server has never heard of the temporary one.

saying these in an interview costs you the question

  • Optimistic means skipping the request and trusting the client.
  • A local patch proves the server accepted the change.
  • On failure just leave the patched value; the user will reload.
  • Rollback can restore the whole cache from one saved copy.
  • Once the guess matches, the response can be ignored.